ソース情報
- リポジトリ
- fabioc-aloha/AlexAgent
- ソースの最終更新活動
- 2026年3月5日 18:53
- 検出された SKILL.md の言語
- 英語
- スター
- 1
- フォーク
- 0
インストール方法
デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。
ソースファイルを確認
インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。
メニュー
デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。
インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
直接コマンドでは確認用 Prompt が省略されます。実行前にソースを確認してください。
npx skills add https://github.com/fabioc-aloha/AlexAgent --skill mcp-development-skillコマンドは1行のまま表示されます。コピー前に横へスクロールして全体を確認してください。
ローカルで確認しますか?SkillsMP が現在取得できるファイルをダウンロードできます。
SKILL.md を表示中
SOC 職業分類に基づく
| name | MCP Development Skill |
| description | **Domain**: AI Infrastructure |
| user-invokable | false |
Domain: AI Infrastructure Inheritance: inheritable Version: 1.1.0 Last Updated: 2026-02-19
⚠️ Staleness Watch: MCP spec is actively versioned. Streamable HTTP replaced HTTP+SSE for remote servers (spec 2025-03-26). Check MCP Changelog when advising on transport selection.
Complete guide to the Model Context Protocol (MCP)—an open standard for connecting AI assistants to external data sources and tools. Covers architecture, server development, client integration, and production deployment patterns.
Before MCP:
┌─────────┐ ┌─────────┐ ┌─────────┐
│ Claude │ │ ChatGPT │ │ Copilot │
└────┬────┘ └────┬────┘ └────┬────┘
│ │ │
▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│Custom │ │Custom │ │Custom │
│Plugin A │ │Plugin A'│ │Plugin A"│
└─────────┘ └─────────┘ └─────────┘
(3 different implementations for same data source)
After MCP:
┌─────────┐ ┌─────────┐ ┌─────────┐
│ Claude │ │ ChatGPT │ │ Copilot │
└────┬────┘ └────┬────┘ └────┬────┘
│ │ │
└───────────────┼───────────────┘
▼
┌────────────┐
│ MCP Server │ (One implementation, many clients)
└────────────┘
| Concept | Description |
|---|---|
| Host | AI application (Claude Desktop, VS Code, etc.) |
| Client | MCP client within the host, manages server connections |
| Server | Provides tools, resources, and prompts via MCP |
| Transport | Communication layer (stdio, Streamable HTTP) |
┌─────────────────────────────────────────────────────────────┐
│ MCP Host │
│ (Claude Desktop, VS Code, IDE, Custom App) │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ │
│ │ MCP Client │ Manages protocol, routing, lifecycle │
│ └──────┬──────┘ │
│ │ │
│ Transport Layer (stdio / Streamable HTTP) │
│ │ │
└─────────┼───────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ MCP Server │
├─────────────────────────────────────────────────────────────┤
│ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
│ │ Tools │ │ Resources │ │ Prompts │ │
│ │ │ │ │ │ │ │
│ │ Functions │ │ Data/Files│ │ Templates │ │
│ │ AI calls │ │ AI reads │ │ AI uses │ │
│ └───────────┘ └───────────┘ └───────────┘ │
└─────────────────────────────────────────────────────────────┘
Functions the AI can execute:
// Tool definition
{
name: "search_issues",
description: "Search GitHub issues in a repository"
user-invokable: false,
inputSchema: {
type: "object",
properties: {
repo: { type: "string", description: "owner/repo format"
user-invokable: false },
query: { type: "string", description: "Search query"
user-invokable: false },
state: {
type: "string",
enum: ["open", "closed", "all"],
default: "open"
}
},
required: ["repo", "query"]
}
}
Tool Design Principles:
Data the AI can read:
// Resource definition
{
uri: "github://repo/owner/repo-name/issues",
name: "Repository Issues",
description: "All issues in the repository"
user-invokable: false,
mimeType: "application/json"
}
// Resource template (dynamic)
{
uriTemplate: "github://repo/{owner}/{repo}/issues/{id}",
name: "GitHub Issue",
description: "A specific GitHub issue"
user-invokable: false,
mimeType: "application/json"
}
Resource Patterns:
Reusable prompt templates:
{
name: "code_review",
description: "Generate a code review for changes"
user-invokable: false,
arguments: [
{
name: "diff",
description: "The code diff to review"
user-invokable: false,
required: true
},
{
name: "focus",
description: "Areas to focus on (security, performance, style)"
user-invokable: false,
required: false
}
]
}
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
const server = new McpServer({
name: "my-mcp-server",
version: "1.0.0"
});
// Register a tool
server.tool(
"get_weather",
"Get current weather for a location",
{
location: {
type: "string",
description: "City name or coordinates"
user-invokable: false
}
},
async ({ location }) => {
const weather = await fetchWeather(location);
return {
content: [
{
type: "text",
text: JSON.stringify(weather, null, 2)
}
]
};
}
);
// Register a resource
server.resource(
"weather://current",
"Current weather data",
"application/json",
async () => ({
contents: [
{
uri: "weather://current",
: ,
: .( ())
}
]
})
);
transport = ();
server.(transport);
from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp.types import Tool, TextContent
server = Server("my-mcp-server")
@server.list_tools()
async def list_tools():
return [
Tool(
name="get_weather",
description="Get current weather for a location",
inputSchema={
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "City name"
}
},
"required": ["location"]
}
)
]
@server.call_tool()
async def call_tool(name: str, arguments: dict):
if name == "get_weather":
weather = await fetch_weather(arguments["location"])
return [TextContent(type="text", text=str(weather))]
raise ValueError(f"Unknown tool: {name}")
async def main():
async with stdio_server() (read_stream, write_stream):
server.run(read_stream, write_stream)
my-mcp-server/
├── package.json
├── tsconfig.json
├── src/
│ ├── index.ts # Entry point
│ ├── server.ts # Server setup
│ ├── tools/
│ │ ├── index.ts # Tool registry
│ │ ├── search.ts # Search tool
│ │ └── create.ts # Create tool
│ ├── resources/
│ │ ├── index.ts # Resource registry
│ │ └── data.ts # Data resources
│ └── utils/
│ ├── auth.ts # Authentication
│ └── cache.ts # Caching
└── tests/
└── tools.test.ts
Default for local servers:
// Claude Desktop config
{
"mcpServers": {
"my-server": {
"command": "node",
"args": ["/path/to/server/dist/index.js"],
"env": {
"API_KEY": "xxx"
}
}
}
}
Characteristics:
For remote/shared servers (replaces deprecated HTTP+SSE as of MCP spec 2025-03-26):
┌────────────┐ HTTPS ┌────────────┐
│ Client │ ◄─────────────────────► │ Server │
│ │ POST /mcp │ │
│ │ (streaming response) │ │
└────────────┘ └────────────┘
Characteristics:
⚠️ HTTP+SSE is deprecated. Old servers used
POST /message+GET /sse. If you encounter an HTTP+SSE server, it is using the legacy transport. Prefer Streamable HTTP for all new remote servers.
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
const transport = new StreamableHTTPServerTransport({ path: "/mcp" });
await server.connect(transport);
// Using MCP in VS Code extension
import { McpClient } from "@modelcontextprotocol/sdk/client/mcp.js";
const client = new McpClient({
name: "vscode-client",
version: "1.0.0"
});
// Connect to server
await client.connect(transport);
// List available tools
const { tools } = await client.listTools();
// Call a tool
const result = await client.callTool({
name: "search_issues",
arguments: { repo: "owner/repo", query: "bug" }
});
// Read a resource
const { contents } = await client.readResource({
uri: "github://repo/owner/repo/readme"
});
Per-User Config (Claude Desktop):
// ~/Library/Application Support/Claude/claude_desktop_config.json
{
"mcpServers": {
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_TOKEN": "${GITHUB_TOKEN}"
}
}
}
}
Workspace Config (VS Code):
// .vscode/mcp.json
{
"servers": {
"project-tools": {
"command": "node",
"args": ["./tools/mcp-server.js"]
}
}
}
// API key from environment
const apiKey = process.env.SERVICE_API_KEY;
if (!apiKey) {
throw new Error("SERVICE_API_KEY required");
}
// OAuth token refresh
async function getValidToken(): Promise<string> {
if (tokenExpired()) {
token = await refreshToken();
}
return token;
}
import { z } from "zod";
const SearchSchema = z.object({
query: z.string().min(1).max(500),
limit: z.number().int().min(1).max(100).default(10),
filters: z.object({
dateFrom: z.string().datetime().optional(),
dateTo: z.string().datetime().optional()
}).optional()
});
server.tool("search", "Search documents", SearchSchema, async (args) => {
const validated = SearchSchema.parse(args);
// Safe to use validated.query, validated.limit, etc.
});
import { RateLimiter } from "./utils/rate-limiter";
const limiter = new RateLimiter({
maxRequests: 100,
windowMs: 60 * 1000 // 1 minute
});
server.tool("expensive_operation", schema, async (args) => {
if (!limiter.tryAcquire()) {
return {
content: [{
type: "text",
text: "Rate limit exceeded. Please try again later."
}],
isError: true
};
}
// Proceed with operation
});
// Restrict file system access
const ALLOWED_PATHS = ["/data", "/tmp"];
function validatePath(requestedPath: string): boolean {
const resolved = path.resolve(requestedPath);
return ALLOWED_PATHS.some(allowed =>
resolved.startsWith(path.resolve(allowed))
);
}
// Restrict network access
const ALLOWED_HOSTS = ["api.example.com", "data.example.com"];
function validateUrl(url: string): boolean {
const parsed = new URL(url);
return ALLOWED_HOSTS.includes(parsed.hostname);
}
server.tool("risky_operation", schema, async (args) => {
try {
const result = await performOperation(args);
return {
content: [{ type: "text", text: JSON.stringify(result) }]
};
} catch (error) {
// Log for debugging
console.error("Operation failed:", error);
// Return user-friendly error
return {
content: [{
type: "text",
text: `Operation failed: ${getUserFriendlyMessage(error)}`
}],
isError: true
};
}
});
function getUserFriendlyMessage(error: unknown): string {
if (error instanceof AuthError) {
return "Authentication failed. Please check your credentials.";
}
if (error instanceof RateLimitError) {
return "Rate limit exceeded. Please try again in a few minutes.";
}
if (error instanceof ValidationError) {
;
}
;
}
import { Logger } from "./utils/logger";
const logger = new Logger("mcp-server");
server.tool("search", schema, async (args, context) => {
const requestId = context.requestId || crypto.randomUUID();
logger.info("Tool called", {
requestId,
tool: "search",
args: sanitizeForLogging(args)
});
const startTime = Date.now();
try {
const result = await performSearch(args);
logger.info("Tool completed", {
requestId,
tool: "search",
durationMs: Date.now() - startTime,
resultCount: result.items.length
});
return { content: [{ type: "text", text: JSON.stringify(result) }] };
} catch (error) {
logger.error("Tool failed", {
requestId,
tool: "search",
: .() - startTime,
: error.
});
error;
}
});
import { LRUCache } from "lru-cache";
const cache = new LRUCache<string, any>({
max: 1000,
ttl: 5 * 60 * 1000 // 5 minutes
});
server.tool("fetch_data", schema, async ({ id }) => {
const cacheKey = `data:${id}`;
// Check cache
const cached = cache.get(cacheKey);
if (cached) {
return { content: [{ type: "text", text: JSON.stringify(cached) }] };
}
// Fetch fresh
const data = await fetchFromAPI(id);
cache.set(cacheKey, data);
return { content: [{ type: "text", text: JSON.stringify(data) }] };
});
import { describe, it, expect } from "vitest";
import { createTestServer } from "./test-utils";
describe("search tool", () => {
it("returns results for valid query", async () => {
const server = createTestServer();
const result = await server.callTool({
name: "search",
arguments: { query: "test", limit: 5 }
});
expect(result.content).toHaveLength(1);
expect(result.isError).toBeFalsy();
const data = JSON.parse(result.content[0].text);
expect(data.items).toHaveLength(5);
});
it("handles invalid input gracefully", async () => {
const server = createTestServer();
const result = await server.callTool({
name: ,
: { : , : - }
});
(result.).();
(result.[].).();
});
});
import { spawn } from "child_process";
import { McpClient } from "@modelcontextprotocol/sdk/client/mcp.js";
describe("MCP Server Integration", () => {
let serverProcess: ChildProcess;
let client: McpClient;
beforeAll(async () => {
// Start server process
serverProcess = spawn("node", ["dist/index.js"]);
// Connect client
client = new McpClient({ name: "test", version: "1.0.0" });
await client.connect(new StdioClientTransport(serverProcess));
});
afterAll(() => {
serverProcess.kill();
});
it("lists tools correctly", async () => {
const { tools } = await client.listTools();
expect(tools.map(t => t.name)).toContain("search");
});
});
| Server | Purpose | Install |
|---|---|---|
| filesystem | Local file access | @modelcontextprotocol/server-filesystem |
| github | GitHub API | @modelcontextprotocol/server-github |
| postgres | Database queries | @modelcontextprotocol/server-postgres |
| puppeteer | Web scraping | @modelcontextprotocol/server-puppeteer |
| memory | Persistent memory | @modelcontextprotocol/server-memory |
| Use Tool When | Use Resource When |
|---|---|
| Action with side effects | Read-only data access |
| Requires input parameters | Static or template URI |
| Returns computed result | Returns stored content |
| May fail or have errors | Generally stable data |
MCP Development skill — Building AI-accessible tools and data sources