add-mcp-resource

Add a new resource or resource template to an existing FastMCP server

9 stars

Best use case

add-mcp-resource is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Add a new resource or resource template to an existing FastMCP server

Teams using add-mcp-resource should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/add-mcp-resource/SKILL.md --create-dirs "https://raw.githubusercontent.com/jpoutrin/product-forge/main/plugins/typescript-experts/skills/add-mcp-resource/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/add-mcp-resource/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How add-mcp-resource Compares

Feature / Agentadd-mcp-resourceStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Add a new resource or resource template to an existing FastMCP server

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# Add MCP Resource

Add a new resource or resource template to an existing FastMCP server.

## Usage

```bash
/add-mcp-resource [resource-uri]
```

## Arguments

- `[resource-uri]`: Optional - URI pattern for the resource (will prompt if not provided)

## Execution Instructions for Claude Code

When this command is run:

1. **Locate the FastMCP server** in the current project
2. **Determine resource type** (static or template)
3. **Gather resource requirements** through interactive questions
4. **Generate resource code** based on configuration
5. **Add resource to server** by modifying existing files

## Interactive Session Flow

### 1. Locate Server

```
Looking for FastMCP server...

Found: src/server.ts

Is this the correct server file? (yes/no):
```

### 2. Resource Type

```
What type of resource do you want to add?

1. Static resource - Fixed URI (e.g., "file:///config/settings.json")
2. Resource template - Dynamic URI with parameters (e.g., "user://{id}/profile")

Select (1-2):
```

### 3. Static Resource Configuration

For static resources:

```
Resource URI:
Example: "file:///logs/app.log", "config://settings", "docs://readme"

URI:
```

```
Resource name (human-readable):
Example: "Application Logs", "Server Configuration"

Name:
```

```
MIME type:
1. text/plain
2. application/json
3. text/markdown
4. text/html
5. Other (specify)

Select (1-5):
```

```
Description (optional):
```

### 4. Resource Template Configuration

For resource templates:

```
URI template pattern:
Use {parameter} syntax for dynamic parts.

Examples:
- "file:///logs/{name}.log"
- "user://{userId}/profile"
- "docs://{category}/{page}"

URI template:
```

```
Resource name:
Example: "User Profiles", "Log Files"

Name:
```

```
Let's define the template parameters.

Parameter: {name}
  Description:
  Required? (yes/no):

  Add auto-completion? (yes/no):
```

If auto-completion:
```
How should auto-completion work?

1. Static list of values
2. Dynamic lookup (I'll implement)
3. Prefix matching (e.g., "Ex" -> "Example")

Select (1-3):
```

### 5. Content Type

```
What type of content does this resource return?

1. Text content
2. Binary content (base64 blob)
3. Multiple items (array of content)

Select (1-3):
```

### 6. Data Source

```
Where does the resource data come from?

1. File system
2. Database
3. External API
4. In-memory/computed
5. Other

Select (1-5):
```

## Generated Code Examples

### Static Resource (Text)

```typescript
server.addResource({
  uri: "{{uri}}",
  name: "{{name}}",
  mimeType: "{{mimeType}}",
  description: "{{description}}",
  async load() {
    // TODO: Implement data loading
    const content = await readFile("path/to/file");
    return {
      text: content,
    };
  },
});
```

### Static Resource (Binary)

```typescript
server.addResource({
  uri: "{{uri}}",
  name: "{{name}}",
  mimeType: "{{mimeType}}",
  async load() {
    // TODO: Load binary data
    const buffer = await readFile("path/to/file");
    return {
      blob: buffer.toString("base64"),
    };
  },
});
```

### Static Resource (Multiple Items)

```typescript
server.addResource({
  uri: "{{uri}}",
  name: "{{name}}",
  mimeType: "{{mimeType}}",
  async load() {
    // Return multiple content items
    return [
      { text: "First section content" },
      { text: "Second section content" },
      { text: "Third section content" },
    ];
  },
});
```

### Resource Template (Basic)

```typescript
server.addResourceTemplate({
  uriTemplate: "{{uriTemplate}}",
  name: "{{name}}",
  mimeType: "{{mimeType}}",
  arguments: [
    {{#each parameters}}
    {
      name: "{{name}}",
      description: "{{description}}",
      required: {{required}},
    },
    {{/each}}
  ],
  async load(args) {
    const { {{parameterNames}} } = args;

    // TODO: Load resource based on parameters
    return {
      text: `Content for ${JSON.stringify(args)}`,
    };
  },
});
```

### Resource Template with Auto-Completion (Static)

```typescript
server.addResourceTemplate({
  uriTemplate: "{{uriTemplate}}",
  name: "{{name}}",
  mimeType: "text/plain",
  arguments: [
    {
      name: "{{paramName}}",
      description: "{{paramDescription}}",
      required: true,
      complete: async (value) => {
        // Static list of completions
        const options = ["option1", "option2", "option3"];
        const filtered = options.filter(opt =>
          opt.toLowerCase().includes(value.toLowerCase())
        );
        return { values: filtered };
      },
    },
  ],
  async load(args) {
    return {
      text: `Content for ${args.{{paramName}}}`,
    };
  },
});
```

### Resource Template with Dynamic Completion

```typescript
server.addResourceTemplate({
  uriTemplate: "{{uriTemplate}}",
  name: "{{name}}",
  mimeType: "application/json",
  arguments: [
    {
      name: "{{paramName}}",
      description: "{{paramDescription}}",
      required: true,
      complete: async (value) => {
        // Dynamic lookup from database/API
        const results = await searchItems(value);
        return {
          values: results.map(r => r.name),
        };
      },
    },
  ],
  async load(args) {
    const item = await findItem(args.{{paramName}});
    if (!item) {
      return { text: "Not found" };
    }
    return {
      text: JSON.stringify(item, null, 2),
    };
  },
});
```

### Resource from File System

```typescript
import { readFile } from "fs/promises";
import { join } from "path";

server.addResourceTemplate({
  uriTemplate: "file:///logs/{name}.log",
  name: "Log Files",
  mimeType: "text/plain",
  arguments: [
    {
      name: "name",
      description: "Name of the log file",
      required: true,
      complete: async (value) => {
        // List available log files
        const files = await readdir("/var/logs");
        const logFiles = files
          .filter(f => f.endsWith(".log"))
          .map(f => f.replace(".log", ""));
        return {
          values: logFiles.filter(f => f.includes(value)),
        };
      },
    },
  ],
  async load(args) {
    const filePath = join("/var/logs", `${args.name}.log`);
    const content = await readFile(filePath, "utf-8");
    return { text: content };
  },
});
```

### Resource from Database

```typescript
server.addResourceTemplate({
  uriTemplate: "user://{userId}/profile",
  name: "User Profiles",
  mimeType: "application/json",
  arguments: [
    {
      name: "userId",
      description: "User ID",
      required: true,
    },
  ],
  async load(args) {
    const user = await db.users.findById(args.userId);
    if (!user) {
      return { text: JSON.stringify({ error: "User not found" }) };
    }
    return {
      text: JSON.stringify({
        id: user.id,
        name: user.name,
        email: user.email,
        createdAt: user.createdAt,
      }, null, 2),
    };
  },
});
```

### Resource from External API

```typescript
server.addResourceTemplate({
  uriTemplate: "weather://{city}",
  name: "Weather Data",
  mimeType: "application/json",
  arguments: [
    {
      name: "city",
      description: "City name",
      required: true,
    },
  ],
  async load(args) {
    const response = await fetch(
      `https://api.weather.example/v1/${encodeURIComponent(args.city)}`
    );

    if (!response.ok) {
      return { text: JSON.stringify({ error: "City not found" }) };
    }

    const data = await response.json();
    return {
      text: JSON.stringify(data, null, 2),
    };
  },
});
```

## File Placement

```
Where should the resource code be added?

1. Inline in server.ts
2. New file in resources/ directory
3. Existing resources file

Select (1-3):
```

## Implementation Notes

1. **Find existing server**: Locate FastMCP server files
2. **Check for resources directory**: Create if needed
3. **Generate imports**: Add necessary imports
4. **Insert code**: Add resource at appropriate location
5. **Match style**: Preserve existing code formatting
6. **Summary**: Show generated resource and URI pattern

Related Skills

zod

9
from jpoutrin/product-forge

Zod schema validation patterns and type inference. Auto-loads when validating schemas, parsing data, validating forms, checking types at runtime, or using z.object/z.string/z.infer in TypeScript.

typescript-import-style

9
from jpoutrin/product-forge

Merge-friendly import formatting (one-per-line, alphabetical). Auto-loads when writing TypeScript/JavaScript imports to minimize merge conflicts in parallel development. Enforces consistent grouping and sorting.

setup-mcp-auth

9
from jpoutrin/product-forge

Configure authentication for an existing FastMCP server

fastmcp

9
from jpoutrin/product-forge

FastMCP TypeScript framework patterns for MCP servers. Auto-loads when building MCP servers, creating tools/resources/prompts, implementing authentication, configuring transports, or working with FastMCP in TypeScript.

add-mcp-tool

9
from jpoutrin/product-forge

Add a new tool to an existing FastMCP server with guided configuration

plan-with-team

9
from jpoutrin/product-forge

Validate plan file ownership

privacy-compliance

9
from jpoutrin/product-forge

GDPR, CCPA, and privacy compliance guidance for data protection. Use when handling personal data, implementing consent management, or ensuring regulatory compliance across jurisdictions.

oauth

9
from jpoutrin/product-forge

OAuth 2.0 and OpenID Connect implementation patterns. Use when implementing authentication, authorization flows, or integrating with OAuth providers like Google, GitHub, or custom identity providers.

mcp-security

9
from jpoutrin/product-forge

Use when securing MCP servers, preventing prompt injection, implementing authorization, validating user input, or building secure multi-agent pipelines. Provides 5-layer defense architecture patterns.

rag-cag-security

9
from jpoutrin/product-forge

Security patterns for RAG and CAG systems with multi-tenant isolation. Use when building retrieval-augmented or cache-augmented generation systems that require tenant isolation, access control, and secure data handling.

chunking-strategies

9
from jpoutrin/product-forge

Document chunking strategies for RAG systems. Use when implementing document processing pipelines to determine optimal chunking approaches based on document type and retrieval requirements.

review-django-commands

9
from jpoutrin/product-forge

Review Django management commands for proper structure and refactor if needed