Install
$ agentstack add skill-nihao555-hub-claude-code-agent-skills-mcp-integration-specialist ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
MCP Integration Specialist
使用此技能当你需要进行 MCP 服务器开发、传输协议配置、OAuth 认证实现、工具注册和资源管理。
目标
产出完整的 MCP 集成方案,包括服务器开发指南、传输协议配置、OAuth 认证流程、工具注册机制和资源管理系统。
核心能力(基于 Claude Code源码)
1. MCP 服务器开发框架
import { Server } from '@modelcontextprotocol/sdk/server/index.js'
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
import {
CallToolRequestSchema,
ListToolsRequestSchema,
ListResourcesRequestSchema,
ReadResourceRequestSchema,
} from '@modelcontextprotocol/sdk/types.js'
// 创建 MCP 服务器
const server = new Server(
{
name: 'my-mcp-server',
version: '1.0.0',
},
{
capabilities: {
tools: {},
resources: {},
},
}
)
// 实现工具列表
server.setRequestHandler(ListToolsRequestSchema, async () => {
return {
tools: [
{
name: 'hello_world',
description: 'Say hello to someone',
inputSchema: {
type: 'object',
properties: {
name: {
type: 'string',
description: 'Name of the person to greet'
},
},
required: ['name'],
},
},
// 更多工具...
],
}
})
// 实现工具调用
server.setRequestHandler(CallToolRequestSchema, async (request) => {
const { name, arguments: args } = request.params
switch (name) {
case 'hello_world': {
const greeting = `Hello, ${args!.name}!`
return {
content: [{ type: 'text', text: greeting }],
}
}
default:
throw new Error(`Unknown tool: ${name}`)
}
})
// 启动服务器
async function main() {
const transport = new StdioServerTransport()
await server.connect(transport)
console.error('MCP Server running on stdio')
}
main().catch(console.error)
2. 传输协议配置
Stdio Transport(本地进程)
import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js'
const transport = new StdioClientTransport({
command: 'node',
args: ['/path/to/mcp-server.js'],
env: {
...process.env,
API_KEY: 'your-api-key',
},
})
SSE Transport(Server-Sent Events)
import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js'
const transport = new SSEClientTransport({
url: new URL('http://localhost:3000/sse'),
requestInit: {
headers: {
'Authorization': `Bearer ${token}`,
},
},
})
HTTP Streaming Transport
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'
const transport = new StreamableHTTPClientTransport({
url: new URL('http://localhost:3000/mcp'),
fetch: createFetchWithInit({
headers: {
'Authorization': `Bearer ${token}`,
},
}),
})
WebSocket Transport
import { WebSocketTransport } from './utils/mcpWebSocketTransport.js'
const transport = new WebSocketTransport({
url: 'ws://localhost:3000/mcp',
tlsOptions: getWebSocketTLSOptions(),
agent: getWebSocketProxyAgent(),
})
3. OAuth 认证实现
import { OAuth2Client } from 'oauth2-client'
class MCPOAuthProvider {
private client: OAuth2Client
private tokenStore: Map = new Map()
constructor(clientId: string, clientSecret: string) {
this.client = new OAuth2Client({
clientId,
clientSecret,
tokenEndpoint: 'https://auth.example.com/oauth/token',
authorizationEndpoint: 'https://auth.example.com/oauth/authorize',
})
}
/**
* 获取访问令牌(自动刷新)
*/
async getAccessToken(serverName: string): Promise {
const cached = this.tokenStore.get(serverName)
if (!cached || this.isTokenExpired(cached)) {
// Token 不存在或已过期,需要刷新或重新认证
const refreshed = await this.refreshOrAuthenticate(serverName)
this.tokenStore.set(serverName, refreshed)
return refreshed.access_token
}
return cached.access_token
}
/**
* 刷新或认证
*/
private async refreshOrAuthenticate(serverName: string): Promise {
const cached = this.tokenStore.get(serverName)
if (cached?.refresh_token) {
try {
// 尝试刷新
const refreshed = await this.client.refreshToken(cached.refresh_token)
return refreshed
} catch (error) {
// 刷新失败,需要重新认证
console.error('Token refresh failed, re-authenticating:', error)
}
}
// 启动认证流程
return this.authenticate(serverName)
}
/**
* 启动 OAuth 认证流程
*/
private async authenticate(serverName: string): Promise {
const authUrl = this.client.code.getAuthorizationUrl({
redirectURI: 'http://localhost:3000/callback',
scope: ['read', 'write'],
})
// 打开浏览器进行认证
await open(authUrl.toString())
// 等待回调
const code = await this.waitForCallback()
// 交换令牌
const token = await this.client.grant({
grantType: 'authorization_code',
code,
redirectURI: 'http://localhost:3000/callback',
})
return token
}
/**
* 检查 Token 是否过期
*/
private isTokenExpired(token: OAuthToken): boolean {
// 提前 5 分钟视为过期
return Date.now() >= (token.expires_at - 5 * 60 * 1000)
}
/**
* 等待认证回调
*/
private async waitForCallback(): Promise {
return new Promise((resolve, reject) => {
// 实现 HTTP 服务器接收回调
const httpServer = require('http').createServer((req: any, res: any) => {
const url = new URL(req.url, 'http://localhost:3000')
const code = url.searchParams.get('code')
if (code) {
resolve(code)
res.writeHead(200)
res.end('Authentication successful! You can close this window.')
} else {
reject(new Error('No code in callback'))
res.writeHead(400)
res.end('Authentication failed')
}
httpServer.close()
})
httpServer.listen(3000)
// 设置超时
setTimeout(() => {
httpServer.close()
reject(new Error('Authentication timeout'))
}, 5 * 60 * 1000) // 5 分钟超时
})
}
}
4. 工具注册系统
interface MCPToolRegistration {
name: string
description: string
inputSchema: Record
handler: (input: Record) => Promise
allowedTools?: string[] // 白名单
disallowedTools?: string[] // 黑名单
}
class MCPToolRegistry {
private tools: Map = new Map()
/**
* 注册工具
*/
register(registration: MCPToolRegistration): void {
this.tools.set(registration.name, registration)
}
/**
* 注销工具
*/
unregister(toolName: string): void {
this.tools.delete(toolName)
}
/**
* 列出所有工具
*/
listTools(): MCPToolRegistration[] {
return Array.from(this.tools.values())
}
/**
* 调用工具
*/
async callTool(
name: string,
input: Record
): Promise {
const tool = this.tools.get(name)
if (!tool) {
throw new Error(`Unknown tool: ${name}`)
}
// 验证输入
this.validateInput(tool.inputSchema, input)
// 执行工具
try {
return await tool.handler(input)
} catch (error) {
return {
content: [
{
type: 'text',
text: `Error executing tool: ${error instanceof Error ? error.message : String(error)}`
},
],
isError: true,
}
}
}
/**
* 验证输入 Schema
*/
private validateInput(
schema: Record,
input: Record
): void {
// 实现 JSON Schema 验证
// 可以使用 ajv 或其他验证库
}
}
5. 资源管理系统
interface MCPResource {
uri: string
name: string
description?: string
mimeType?: string
}
class MCPResourceManager {
private resources: Map = new Map()
/**
* 注册资源
*/
register(resource: MCPResource): void {
this.resources.set(resource.uri, resource)
}
/**
* 列出所有资源
*/
listResources(): MCPResource[] {
return Array.from(this.resources.values())
}
/**
* 读取资源
*/
async readResource(uri: string): Promise {
const resource = this.resources.get(uri)
if (!resource) {
throw new Error(`Resource not found: ${uri}`)
}
// 根据 URI 类型读取资源
if (uri.startsWith('file://')) {
return this.readFileResource(uri)
} else if (uri.startsWith('http://') || uri.startsWith('https://')) {
return this.readHttpResource(uri)
} else {
throw new Error(`Unsupported resource URI: ${uri}`)
}
}
/**
* 读取文件资源
*/
private async readFileResource(uri: string): Promise {
const filePath = uri.replace('file://', '')
const content = await fs.promises.readFile(filePath, 'utf-8')
return {
uri,
mimeType: 'text/plain',
text: content,
}
}
/**
* 读取 HTTP 资源
*/
private async readHttpResource(uri: string): Promise {
const response = await fetch(uri)
const contentType = response.headers.get('content-type') || 'text/plain'
const text = await response.text()
return {
uri,
mimeType: contentType,
text,
}
}
}
6. MCP 客户端连接管理
class MCPConnectionManager {
private connections: Map = new Map()
/**
* 连接到 MCP 服务器
*/
async connect(
serverName: string,
config: MCPServerConfig
): Promise {
// 检查是否已连接
const existing = this.connections.get(serverName)
if (existing && existing.status === 'connected') {
return existing
}
// 创建传输
const transport = this.createTransport(config)
// 创建客户端
const client = new Client({
name: 'claude-code',
version: pkg.version,
})
// 连接
await client.connect(transport)
// 获取服务器能力
const tools = await client.listTools()
const resources = await client.listResources()
const prompts = await client.listPrompts()
// 存储连接
const connection: MCPServerConnection = {
serverName,
config,
client,
transport,
tools,
resources,
prompts,
status: 'connected',
}
this.connections.set(serverName, connection)
// 发送连接事件
this.notifyConnected(serverName)
return connection
}
/**
* 断开连接
*/
async disconnect(serverName: string): Promise {
const connection = this.connections.get(serverName)
if (connection) {
await connection.client.close()
this.connections.delete(serverName)
this.notifyDisconnected(serverName)
}
}
/**
* 重新连接
*/
async reconnect(serverName: string): Promise {
await this.disconnect(serverName)
const config = this.getConnectionConfig(serverName)
await this.connect(serverName, config)
}
/**
* 创建传输
*/
private createTransport(config: MCPServerConfig): Transport {
switch (config.type) {
case 'stdio':
return new StdioClientTransport({
command: config.command,
args: config.args,
env: config.env,
})
case 'sse':
return new SSEClientTransport({
url: new URL(config.url),
requestInit: config.headers ? { headers: config.headers } : undefined,
})
case 'http':
return new StreamableHTTPClientTransport({
url: new URL(config.url),
fetch: createFetchWithInit(config.fetchOptions),
})
case 'websocket':
return new WebSocketTransport({
url: config.url,
tlsOptions: config.tlsOptions,
agent: config.proxyAgent,
})
default:
throw new Error(`Unsupported transport type: ${(config as any).type}`)
}
}
}
工作流程
第一步:需求分析 (15 分钟)
- 确定集成场景
- 需要哪些 MCP 服务器?
- 使用什么传输协议?
- 是否需要 OAuth 认证?
- 需要暴露哪些工具和资源?
- 选择传输协议
`` 本地进程 → Stdio 远程 HTTP → SSE 或 HTTP Streaming 实时双向 → WebSocket ``
第二步:服务器开发 (40 分钟)
- 搭建服务器框架
- 实现工具列表
- 实现工具处理器
- 实现资源管理
- 添加错误处理
第三步:客户端集成 (30 分钟)
- 配置连接管理器
- 实现 OAuth 认证
- 注册工具和资源
- 测试连接和调用
规则
- ✅ 使用标准的 MCP SDK API
- ✅ 实现完整的错误处理
- ✅ 提供详细的工具描述
- ✅ 验证所有输入参数
- ✅ 实现连接重试机制
- ❌ 不要硬编码凭证
- ❌ 不要忽略连接超时
- ❌ 不要暴露敏感信息作为资源
- ❌ 不要忘记清理连接资源
输出格式
📊 MCP 服务器清单
| 服务器名称 | 传输类型 | 工具数量 | 资源数量 | 认证方式 |
|-----------|---------|---------|---------|---------|
| github | stdio | 15 | 0 | OAuth |
| filesystem| stdio | 5 | ∞ | None |
| web | http | 3 | ∞ | None |
🏗️ 架构图
展示 MCP 客户端和服务器的连接关系。
📝 实现代码
提供完整的服务器和客户端实现代码。
🔍 测试计划
连接测试、工具调用测试、认证流程测试计划。
⚠️ 风险评估
| 风险项 | 可能性 | 影响程度 | 缓解措施 | |-------|--------|----------|----------| | 认证失败 | 中 | 高 | 自动刷新 + 降级策略 | | 连接超时 | 高 | 中 | 重试机制 + 超时保护 | | 工具执行错误 | 中 | 中 | 错误捕获 + 用户提示 |
交付物清单
最终报告应包含:
- [ ] MCP 服务器开发指南
- [ ] 传输协议配置方案
- [ ] OAuth 认证实现
- [ ] 工具注册系统
- [ ] 资源管理系统
- [ ] 连接管理器实现
- [ ] 测试计划和测试用例
🤖 AI IDE 开发指南
本部分指导 AI IDE 按照 Claude Code的最佳实践开发 MCP 集成系统。
AI IDE 开发前检查
MCP 环境验证
必须检查:
- @modelcontextprotocol/sdk 已安装
- 传输协议依赖可用
- OAuth 库已安装(如需要)
- 网络连通性正常
警告信号:
- 缺少必要的依赖包
- 端口被占用
- 防火墙阻止连接
服务器配置
必须存在:
- 服务器名称唯一
- 传输配置完整
- 认证配置安全
- 超时配置合理
AI IDE 开发中指导
实时 MCP 开发监控
当开发 MCP 集成时,AI IDE应该:
- Schema 验证
```typescript // ✅ 正确的 Schema 定义 const schema = { type: 'object', properties: { name: { type: 'string', description: 'User name' }, age: { type: 'number', minimum: 0 }, }, required: ['name'], }
// ❌ 避免的模式 const schema = { type: 'object', properties: {} // 空的属性定义 } // AI IDE 应该:建议添加具体的属性定义 ```
- 错误处理检查
``typescript // ✅ 完整的错误处理 try { const result = await client.callTool(params) return result } catch (error) { return { content: [{ type: 'text', text: MCP Error: ${error instanceof Error ? error.message : String(error)}` }], isError: true, } }
// ❌ 避免的模式 const result = await client.callTool(params) // 无错误处理 // AI IDE 应该:建议添加 try-catch ```
- 连接生命周期管理
``typescript // AI IDE 应该确保正确管理连接 class MyService { async shutdown() { await connectionManager.disconnect('server-name') } } ``
OAuth 安全管理
AI IDE应该提供:
- 凭证加密存储: 不使用明文
- Token 自动刷新: 过期前刷新
- 安全回调处理: 验证 state 参数
- 错误日志脱敏: 不泄露敏感信息
AI IDE 完成后验证
MCP 集成健康度评分卡
服务器开发 (0-10分):
- 工具定义完整
- Schema 验证正确
- 错误处理完善
传输配置 (0-10分):
- 协议选择合理
- 连接稳定
- 超时配置适当
OAuth 认证 (0-10分):
- 流程完整
- Token 管理安全
- 刷新机制可靠
资源管理 (0-10分):
- 资源注册完整
- 读取正确
- MIME 类型准确
总分评级:
- 90-100: Excellent (生产就绪)
- 75-89: Good (少量优化)
- 60-74: Fair (需要改进)
- {...})
test('reuses existing connection', async () => {...})
# 2. 工具调用测试
test('calls tool successfully', async () => {...})
test('handles tool errors', async () => {...})
# 3. OAuth 测试
test('authenticates with OAuth', async () => {...})
test('refreshes expired token', async () => {...})
# 4. 资源管理测试
test('lists resources', async () => {...})
test('reads file resource', async () => {...})
AI IDE 常见陷阱检测
🔴 高危问题(必须修复)
// ❌ 凭证硬编码
const CLIENT_SECRET = 'abc123...' // 直接写在代码里!
// AI IDE 应该:建议使用环境变量
// ❌ Token 明文存储
localStorage.setItem('token', token) // 不安全!
// AI IDE 应该:建议使用加密存储
// ❌ 无超时保护
await client.callTool(params) // 可能永远等待
// AI IDE 应该:建议添加 AbortSignal.timeout()
🟡 中等风险(建议优化)
// ⚠️ Schema 不完整
const schema = {
type: 'object',
properties: {
name: { type: 'string' } // 缺少 description
}
}
// AI IDE 应该:建议添加 description
🟢 低风险(可选改进)
// 💡 可以优化的模式
const tools = await client.listTools()
console.log(tools) // 基础日志
// AI IDE 可以建议:使用结构化日志
AI IDE 代码审查检查清单
在 PR/MR阶段,AI IDE应该自动检查:
服务器开发
- [ ] 工具定义符合规范
- [ ] Input Schema 完整
- [ ] 错误处理完善
- [ ] 资源管理正确
传输配置
- [ ] 协议选择合理
- [ ] 连接参数完整
- [ ] 超时配置适当
- [ ] 重试机制实现
OAuth 认证
- [ ] 流程符合 OAuth 2.0规范
- [ ] State 参数验证
- [ ] Token 加密存储
- [ ] 自动刷新实现
安全性
- [ ] 凭证不硬编码
- [ ] 敏感信息不泄露
- [ ] 输入验证完整
- [ ] 错误信息脱敏
AI IDE 集成实现示例
…
## Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- **Author:** [nihao555-hub](https://github.com/nihao555-hub)
- **Source:** [nihao555-hub/claude-code-agent-skills](https://github.com/nihao555-hub/claude-code-agent-skills)
- **License:** MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.