MCP Integration Assistant — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited MCP Integration Assistant (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
This skill guides the design and implementation of a Model Context Protocol (MCP) server that exposes an external system, API, or data source as tools, resources, or prompts for AI agents. It designs the tool schema, writes the server handler code, generates the client configuration snippet, and explains how to test the integration. The output is a working MCP server ready for use with Claude Desktop, Claude Code, Cline, or any MCP-compatible agent.
Use this when you want to give an AI agent access to a new system — a database, an internal API, a third-party service, a file system, or any data source — through the standard MCP protocol.
Copy this file to .agents/skills/mcp-integration-assistant/SKILL.md in your project root.
Then describe what you want to expose and ask:
Describe the external system, what operations the agent should be able to perform, and any auth requirements.
Add the "Prompt / Instructions" section to your .cursorrules file. Describe the system you want to expose and ask Cursor to design the MCP server.
Describe the target system and the operations you want to expose, then include the instructions below. Provide any relevant API docs or existing SDK code.
When asked to design an MCP integration, follow these steps:
Most integrations primarily use Tools. Resources are best for large, browseable data. Prompts are optional.
name: lowercase, hyphenated, descriptive verb-noun (e.g., search-issues, create-record, get-user)description: one sentence. Explain what the tool does AND what an agent should use it for. Good descriptions help the agent decide when to call the tool.inputSchema: JSON Schema object defining all parameters with:type, description, and required for each fieldenum values where the set of options is knownexamples or default values where applicable@modelcontextprotocol/sdk package: 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: "your-server-name",
version: "1.0.0",
});
server.tool("tool-name", "Description", { param: z.string() }, async ({ param }) => {
// implementation
return { content: [{ type: "text", text: result }] };
});
const transport = new StdioServerTransport();
await server.connect(transport);Use Zod for input validation. Return { content: [{ type: "text", text: "..." }] } for success. Return { content: [...], isError: true } for errors.
const apiKey = process.env.MY_SERVICE_API_KEYclaude_desktop_config.json: {
"mcpServers": {
"your-server-name": {
"command": "node",
"args": ["/absolute/path/to/dist/index.js"],
"env": {
"MY_SERVICE_API_KEY": "your-key-here"
}
}
}
}Also show the equivalent for Claude Code / Cline if different.
node dist/index.js and send JSON-RPC messages via stdinnpx @modelcontextprotocol/inspector) for interactive testing## MCP Integration: [System Name]
### Tools Designed
| Tool Name | Description | Key Parameters |
|-----------|-------------|----------------|
| ... | ... | ... |
### Server Code[Full server implementation]
### package.json dependencies[Required packages]
### Client Configuration[claude_desktop_config.json snippet]
### Environment Variables
| Variable | Required | Description |
|----------|----------|-------------|
| ... | ... | ... |
### Testing
[How to test each tool]Input to Agent:
"Use the MCP Integration Assistant skill to build an MCP server that lets an AI agent search and create Notion pages. Auth is via a Notion integration token."
Output from Agent:
## MCP Integration: Notion
>
### Tools Designed | Tool Name | Description | Key Parameters | |-----------|-------------|----------------| |search-notion| Search for pages and databases by title or content. Use when the agent needs to find existing Notion content. |query(string),filter(page/database) | |get-notion-page| Retrieve the full content of a Notion page by ID. Use when the agent needs to read a specific page. |pageId(string) | |create-notion-page| Create a new page in a Notion database. Use when the agent needs to write structured data to Notion. |parentId,title,properties,content|
>
### Server Code ```typescript import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { z } from "zod"; import { Client } from "@notionhq/client";
>
const notionToken = process.env.NOTION_TOKEN; if (!notionToken) throw new Error("NOTION_TOKEN environment variable is required");
>
const notion = new Client({ auth: notionToken });
>
const server = new McpServer({ name: "notion-mcp", version: "1.0.0", });
>
server.tool( "search-notion", "Search Notion pages and databases by title or content. Use when you need to find existing Notion content before reading or updating it.", { query: z.string().describe("The search query"), filter: z.enum(["page", "database"]).optional().describe("Filter results to pages or databases only"), }, async ({ query, filter }) => { try { const response = await notion.search({ query, filter: filter ? { property: "object", value: filter } : undefined, }); const results = response.results.map((r: any) => ({ id: r.id, title: r.properties?.title?.title?.[0]?.plain_text ?? r.title?.[0]?.plain_text ?? "Untitled", url: r.url, type: r.object, })); return { content: [{ type: "text", text: JSON.stringify(results, null, 2) }] }; } catch (err: any) { return { content: [{ type: "text", text: Error: ${err.message} }], isError: true }; } } );>
server.tool( "get-notion-page", "Retrieve the full content of a Notion page by its ID. Use when you have a page ID from search results and need to read the content.", { pageId: z.string().describe("The Notion page ID") }, async ({ pageId }) => { try { const [page, blocks] = await Promise.all([ notion.pages.retrieve({ page_id: pageId }), notion.blocks.children.list({ block_id: pageId }), ]); return { content: [{ type: "text", text: JSON.stringify({ page, blocks: blocks.results }, null, 2) }] }; } catch (err: any) { return { content: [{ type: "text", text: Error: ${err.message} }], isError: true }; } } );>
const transport = new StdioServerTransport(); await server.connect(transport); ```
>
### Client Configuration ``json { "mcpServers": { "notion-mcp": { "command": "node", "args": ["/absolute/path/to/notion-mcp/dist/index.js"], "env": { "NOTION_TOKEN": "secret_your_integration_token_here" } } } } ``>
### Environment Variables | Variable | Required | Description | |----------|----------|-------------| | NOTION_TOKEN | Yes | Notion integration token from https://www.notion.so/my-integrations |>
### Testing 1. Runnpx @modelcontextprotocol/inspector node dist/index.jsto open the interactive inspector 2. Testsearch-notionwith a query matching a known page title 3. Copy the returned ID and testget-notion-pagewith it 4. Testcreate-notion-pagewith a known database ID and verify the page appears in Notion
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.