MCP Servers and Resource Integration
The Model Context Protocol (MCP) is an open standard created by Anthropic that defines how AI models connect to external data sources and tools. If tool use lets Claude call functions you define in your application, MCP goes a step further: it provides a standardized way for Claude to discover, connect to, and interact with external systems — databases, APIs, file systems, and more — without custom integration code for each one.
MCP is to AI tool integration what USB was to peripheral connectivity: a universal protocol that means you build the adapter once and it works everywhere.
What MCP Actually Is
At its core, MCP defines a client-server protocol. An MCP server exposes capabilities — tools, resources, and prompts — through a standardized interface. An MCP client (like Claude Desktop, Claude Code, or your own application) connects to those servers and makes their capabilities available to the AI model.
The protocol defines three types of capabilities:
Tools — Functions the AI can call, similar to regular tool use but discovered dynamically. An MCP database server might expose query, list_tables, and describe_table as tools.
Resources — Data the AI can read, like files, database records, or API responses. Resources have URIs and can be listed, read, and subscribed to for changes.
Prompts — Reusable prompt templates that the server provides. A code review MCP server might offer a security_audit prompt template that structures the review according to its best practices.
The key distinction from regular tool use is that MCP tools are discovered at runtime. Your application does not need to hardcode tool definitions — it connects to an MCP server, asks what tools are available, and presents them to Claude dynamically.
The MCP Architecture
An MCP setup has three layers:
+---------------+ +----------------+ +-------------------+
| MCP Client |---->| MCP Server |---->| External System |
| (Claude, App) |<----| (middleware) |<----| (DB, API, Files) |
+---------------+ +----------------+ +-------------------+
MCP Client — The application hosting the AI model. Claude Desktop and Claude Code are built-in MCP clients. You can also build your own using the MCP SDKs.
MCP Server — A lightweight process that wraps an external system and exposes it through the MCP protocol. Each server handles one concern: a database server, a GitHub server, a file system server.
External System — The actual data source or service: PostgreSQL, the GitHub API, a local file system, a Slack workspace, a vector database.
MCP servers communicate with clients over two transport types:
- stdio — The server runs as a subprocess and communicates via standard input/output. Best for local tools and development.
- Streamable HTTP — The server runs as an HTTP service with streaming support. Best for remote servers and production deployments. (This replaces the earlier SSE transport.)
Setting Up MCP Servers
MCP servers are configured in a JSON configuration file. For Claude Desktop, this is claude_desktop_config.json. For Claude Code, this is the project's .mcp.json file or .claude/settings.json.
Here is a configuration that connects to a local SQLite database and a GitHub server:
{
"mcpServers": {
"sqlite": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-sqlite",
"/path/to/your/database.db"
]
},
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_your_token_here"
}
}
}
}
Each server entry specifies:
- command — The executable to run
- args — Command-line arguments, typically including the server package and connection details
- env — Environment variables the server needs (API keys, tokens, connection strings)
Once configured, restarting your MCP client will connect to these servers. Claude can then use the tools and resources they expose without any additional prompting.
Working with MCP Resources
Resources are data that Claude can read through the MCP protocol. Each resource has a URI that identifies it, and Claude can list available resources and read their contents.
For a filesystem MCP server, resources might look like:
file:///Users/project/src/index.ts
file:///Users/project/package.json
file:///Users/project/README.md
For a database MCP server:
db://main/tables
db://main/tables/users/schema
db://main/tables/users/data
Resources support two access patterns:
Direct read — Claude requests a specific resource by URI and gets its contents. This is analogous to reading a file or querying a table.
Resource templates — Parameterized URIs that Claude can fill in. For example, db://main/tables/{table_name}/schema lets Claude read the schema of any table by providing the table name.
In Claude Code, when an MCP server exposes resources, Claude can use them as context for its work. If you have a database MCP server running, Claude can read table schemas to understand your data model before writing queries — without you needing to paste the schema into the conversation.
Working with MCP Tools
MCP tools work exactly like regular Claude tool use, but they are provided by the MCP server rather than hardcoded in your application.
When Claude connects to an MCP server, it receives the tool definitions (name, description, input schema) through the protocol. From Claude's perspective, MCP tools and manually defined tools are identical — it calls them the same way.
For example, a PostgreSQL MCP server might expose:
{
"name": "query",
"description": "Execute a read-only SQL query against the connected PostgreSQL database. Returns results as JSON rows. Only SELECT queries are allowed.",
"inputSchema": {
"type": "object",
"properties": {
"sql": {
"type": "string",
"description": "The SQL SELECT query to execute"
}
},
"required": ["sql"]
}
}
A GitHub MCP server might expose:
{
"name": "create_pull_request",
"description": "Create a new pull request in the specified repository.",
"inputSchema": {
"type": "object",
"properties": {
"repo": {
"type": "string",
"description": "Repository in 'owner/repo' format"
},
"title": {
"type": "string",
"description": "Pull request title"
},
"body": {
"type": "string",
"description": "Pull request description in markdown"
},
"head": {
"type": "string",
"description": "Branch containing changes"
},
"base": {
"type": "string",
"description": "Branch to merge into, e.g., 'main'"
}
},
"required": ["repo", "title", "head", "base"]
}
}
Claude uses these tools based on the conversation context. If you ask "show me the users table schema," Claude calls the database server's tool. If you ask "create a PR for my changes," Claude calls the GitHub server's tool. You do not need to tell Claude which MCP server to use — it matches the request to the most relevant tool automatically.
MCP Prompts
MCP servers can expose prompt templates — reusable, parameterized prompts that encode the server's domain knowledge. This is less commonly used than tools and resources but is valuable for standardizing workflows.
A code review MCP server might expose a prompt like:
{
"name": "security_review",
"description": "Structured security review prompt with OWASP focus",
"arguments": [
{
"name": "code",
"description": "The code to review",
"required": true
},
{
"name": "threat_model",
"description": "Description of the threat model",
"required": false
}
]
}
When Claude (or the MCP client) selects this prompt, the server returns a fully structured prompt with the arguments filled in. This ensures consistent review quality regardless of who triggers the review or how they phrase the request.
Practical Use Cases
Database Integration
A database MCP server is one of the most immediately useful integrations. It lets Claude:
- Explore your schema (list tables, describe columns, show relationships)
- Write and execute queries based on natural language requests
- Analyze query results and explain patterns in the data
- Help debug data issues by examining actual records
Here is an example of how a conversation flows with a database MCP server connected:
User: "Which users signed up last week but haven't completed onboarding?"
Claude's process:
1. Calls list_tables to see available tables
2. Calls describe_table for 'users' and 'onboarding_steps' tables
3. Writes a SQL query joining the tables with date filters
4. Calls query to execute the SQL
5. Returns the results with analysis and suggested next steps
You did not need to tell Claude the table names, column names, or query syntax. The MCP server provided the schema, and Claude reasoned about the correct query from your natural language request.
File System Access
A filesystem MCP server gives Claude access to read and navigate project files. This is particularly transformative in Claude Desktop, where Claude does not have built-in file access (unlike Claude Code, which has this natively).
With a filesystem MCP server, Claude Desktop can:
- Read your project files and understand the codebase structure
- Write new files or update existing ones
- Search for patterns across the project
- Navigate directory structures to find relevant code
API Integration
MCP servers can wrap any external API. Common integrations include:
- GitHub — Read issues, create pull requests, review code, search repositories
- Slack — Read channel history, search messages, post updates
- Jira/Linear — Create tickets, update status, query backlogs
- Cloud providers — Check resource status, read logs, manage deployments
- Monitoring tools — Read metrics, check active alerts, query dashboards
Each integration follows the same pattern: an MCP server wraps the API, exposes relevant operations as tools, and Claude uses them naturally in conversation.
Vector Database and Semantic Search
A vector database MCP server lets Claude search your documentation, codebase embeddings, or knowledge base using semantic search. This is the foundation for RAG (Retrieval-Augmented Generation) workflows:
User: "How does our authentication system handle token refresh?"
Claude's process:
1. Calls vector_search with a query about token refresh
2. Receives the most relevant documentation chunks and code snippets
3. Synthesizes an answer grounded in your actual documentation
4. Cites the specific documents it referenced
This pattern ensures Claude's answers are based on your actual documentation rather than its general training data.
Building Your Own MCP Server
The MCP specification is open, and SDKs are available in TypeScript and Python. Building a custom MCP server is straightforward when you have an internal system that Claude should be able to access.
Here is a minimal MCP server in TypeScript that exposes a single tool:
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
const server = new McpServer({
name: "inventory-server",
version: "1.0.0",
});
// Define a tool
server.tool(
"check_inventory",
"Check the current inventory level for a product by SKU. Returns quantity in stock, warehouse location, and restock date if applicable.",
{
sku: z.string().describe("Product SKU, e.g., 'WIDGET-001'"),
},
async ({ sku }) => {
const inventory = await getInventoryFromDatabase(sku);
return {
content: [
{
type: "text",
text: JSON.stringify(inventory, null, 2),
},
],
};
}
);
// Define a resource
server.resource(
"inventory://products",
"List of all products in the inventory system",
async () => {
const products = await getAllProducts();
return {
contents: [
{
uri: "inventory://products",
text: JSON.stringify(products, null, 2),
mimeType: "application/json",
},
],
};
}
);
// Start the server
const transport = new StdioServerTransport();
await server.connect(transport);
And the equivalent in Python using FastMCP:
import json
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("inventory-server")
@mcp.tool()
def check_inventory(sku: str) -> str:
"""Check the current inventory level for a product by SKU.
Returns quantity in stock, warehouse location, and restock date if applicable.
Args:
sku: Product SKU, e.g., 'WIDGET-001'
"""
inventory = get_inventory_from_database(sku)
return json.dumps(inventory, indent=2)
@mcp.resource("inventory://products")
def list_products() -> str:
"""List of all products in the inventory system."""
products = get_all_products()
return json.dumps(products, indent=2)
mcp.run()
The server handles all MCP protocol details — serialization, transport, capability negotiation. You just define what tools and resources to expose.
MCP in Claude Code vs Claude Desktop
Claude Code and Claude Desktop both support MCP, but the value proposition differs:
Claude Code already has built-in file system access, command execution, and code editing tools. MCP adds value for:
- Database access (querying your development database directly)
- External API integration (GitHub, Jira, Slack from within your coding session)
- Custom internal tools specific to your team's workflow
- Vector search over documentation or codebase embeddings
Claude Desktop does not have built-in file or command access. MCP is more transformative here because it provides capabilities Claude Desktop lacks entirely:
- Reading and writing files on your local system
- Running commands and scripts
- Querying databases
- Any external system interaction
Configure MCP servers for Claude Code in your project's .mcp.json file so the tools are available automatically when anyone opens the project:
{
"mcpServers": {
"postgres": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-postgres",
"postgresql://localhost:5432/mydb"
]
},
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}"
}
}
}
}
Note the use of ${GITHUB_TOKEN} to reference an environment variable rather than hardcoding a token in the configuration file. This keeps secrets out of version control.
Prompting Strategies with MCP
When MCP servers are connected, your prompts can be more direct and action-oriented because Claude has real capabilities, not just knowledge.
Without MCP:
Can you help me understand what tables are in our database? Here is the
schema dump: [paste 500 lines of SQL DDL]
With a database MCP server:
List all tables in the database, then describe the schema of any tables
related to user authentication. I want to understand how sessions and
tokens are stored.
The second prompt is shorter and clearer because you do not need to provide the schema yourself — Claude can discover it through the MCP server.
Cross-server workflows are where MCP truly shines. With multiple servers connected, Claude can:
Look at the open GitHub issues labeled "data-migration", check our
database schema for the tables mentioned in those issues, and draft
a migration plan that addresses each issue. Save the plan as a
markdown file in the docs/ directory.
This single prompt uses the GitHub MCP server (to read issues), the database MCP server (to inspect schemas), and the filesystem MCP server (to write the output file). Claude coordinates across all three automatically.
Security Considerations
MCP servers have access to real systems with real data. Security is essential.
Principle of least privilege — MCP servers should have only the permissions they need. A database server that only needs to read data should connect with a read-only database user. A GitHub server that only needs to read issues should use a token with issues:read scope, not full repository access.
Environment isolation — Keep MCP server credentials in environment variables, not in configuration files that might be committed to version control. Use the env field in MCP configuration with variable references like ${GITHUB_TOKEN}.
Read-only by default — When possible, configure MCP servers in read-only mode. A database server that only allows SELECT queries is far safer than one that allows arbitrary SQL. Escalate to write access only when explicitly needed and with appropriate safeguards.
Audit logging — For production MCP deployments, log every tool call and its parameters. If Claude calls delete_record or drop_table, you need to know when, with what parameters, and in response to what user request.
Input validation — MCP servers should validate all inputs from the client. Do not trust that Claude will always provide valid parameters — implement the same input validation you would for any API endpoint.
Network security — Servers using the Streamable HTTP transport are network services. Apply standard HTTP security practices: TLS encryption, authentication tokens, rate limiting, and request validation.
Key Takeaways
- MCP is an open protocol that standardizes how AI models connect to external data sources and tools — build the adapter once, use it everywhere
- MCP servers expose three capability types: tools (functions to call), resources (data to read), and prompts (reusable templates)
- MCP tools work identically to regular Claude tool use from the model's perspective — the protocol handles discovery and communication automatically
- Database MCP servers are one of the most immediately useful integrations, letting Claude explore schemas and run queries from natural language
- Building a custom MCP server is straightforward with the TypeScript and Python SDKs — define your tools and resources, and the SDK handles the protocol
- Cross-server workflows are where MCP provides the most value, letting Claude coordinate across databases, APIs, and file systems in a single task
- Security is critical: use scoped tokens, prefer read-only access, keep credentials in environment variables, validate inputs, and log all tool calls
- Configure project-specific MCP servers in
.mcp.jsonso they are available automatically for every team member
Discussion
Sign in to join the discussion.

