Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions docs/api-reference/mcp-server.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,22 @@ server.registerTool(config, handler): this;

Registers a tool, optionally bound to a view. See [registerTool](/api-reference/register-tool) for the full config and handler.

### `registerResource`

```ts
server.registerResource(config, handler): this;
```

Registers a [resource](/build/resources) the host can read by URI, static or template-based. See [registerResource](/api-reference/register-resource).

### `registerPrompt`

```ts
server.registerPrompt(config, handler): this;
```

Registers a [prompt](/build/prompts) the user can invoke from the host's prompt menu. See [registerPrompt](/api-reference/register-prompt).

### `use`

```ts
Expand Down
90 changes: 90 additions & 0 deletions docs/api-reference/register-prompt.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
---
title: registerPrompt
description: "Ship a reusable prompt users can invoke"
---

`registerPrompt` adds a [prompt](/build/prompts) to your server: a named, parameterized message template the user picks from the host's prompt menu. The handler returns the messages the host inserts into the conversation.

## Example

A prompt that takes one argument and returns a single user message.

```ts server.ts
import { McpServer } from "skybridge/server";
import { z } from "zod";

const server = new McpServer({ name: "travel", version: "1.0" }).registerPrompt(
{
name: "trip-summary",
title: "Trip summary",
description: "Summarize a trip to a destination.",
argsSchema: { destination: z.string() },
},
({ destination }) => ({
messages: [
{
role: "user",
content: { type: "text", text: `Summarize a trip to ${destination}.` },
},
],
}),
);
```

## Signature

```ts
server.registerPrompt(config: PromptConfig, handler: PromptHandler): McpServer;
```

The config-object form returns the server, so it chains alongside [`registerTool`](/api-reference/register-tool) and [`registerResource`](/api-reference/register-resource).

## Config

```ts
type PromptConfig = {
name: string;
title?: string;
description?: string;
argsSchema?: ZodRawShape; // Zod shape; validates args and types the handler
};
```

### `name`, `title`, `description`

`name` identifies the prompt; `title` and `description` are what the host shows in its prompt menu.

### `argsSchema`

A [Zod](https://zod.dev/) raw shape whose fields become the prompt's arguments. It validates what the host passes and types the handler's input. Wrap a field in `completable()` to autocomplete it as the user types, see [Completions](/build/prompts#completions).

## Handler

Receives the validated arguments and returns the messages to insert.

```ts
type PromptHandler = (
args: Args,
extra: RequestHandlerExtra,
) => Promise<{
description?: string;
messages: Array<{
role: "user" | "assistant";
content: ContentBlock;
}>;
}>;
```

Each message's `content` is a standard MCP [`ContentBlock`](/api-reference/register-tool#content-helpers), most often `{ type: "text", text }`.

<CardGroup cols={3}>
<Card title="Register Prompts" icon="message-square" href="/build/prompts">
The guide, with completions
</Card>
<Card title="registerResource" icon="file-text" href="/api-reference/register-resource">
Expose readable content
</Card>
<Card title="McpServer" icon="server" href="/api-reference/mcp-server">
The server you register on
</Card>
</CardGroup>
135 changes: 135 additions & 0 deletions docs/api-reference/register-resource.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
---
title: registerResource
description: "Expose a resource the host can read"
---

`registerResource` adds a [resource](/build/resources) to your server: addressable content a host can read by URI, such as reference docs, a data file, or a live-generated report. Pass a `uri` for a fixed resource or a `template` for a family of URIs.

## Example

A static Markdown document at a fixed URI.

```ts server.ts
import { McpServer } from "skybridge/server";

const server = new McpServer({ name: "shop", version: "1.0" }).registerResource(
{
name: "pricing",
uri: "docs://pricing",
title: "Pricing",
description: "Current plan pricing, in Markdown.",
mimeType: "text/markdown",
},
async (uri) => ({
contents: [{ uri: uri.href, text: await loadPricingDoc() }],
}),
);
```

## Signature

```ts
server.registerResource(config: ResourceConfig, handler: ReadHandler): McpServer;
```

The config-object form returns the server, so it chains alongside [`registerTool`](/api-reference/register-tool) and [`registerPrompt`](/api-reference/register-prompt).

## Config

Provide either `uri` (static) or `template` (dynamic), never both. The remaining fields are the resource's metadata.

```ts
type ResourceConfig =
| { name: string; uri: string } & ResourceMetadata
| { name: string; template: ResourceTemplate } & ResourceMetadata;

type ResourceMetadata = {
title?: string;
description?: string;
mimeType?: string;
_meta?: Record<string, unknown>;
};
```

### `name`

Identifier for the resource, unique per server.

### `uri`

The fixed URI a static resource is read from, e.g. `docs://pricing`. The handler receives this back as a `URL`.

<Warning>
The `ui://views/` namespace is reserved for Skybridge view resources. Registering a resource under it throws.
</Warning>

### `template`

A [`ResourceTemplate`](https://github.com/modelcontextprotocol/typescript-sdk) for a family of URIs, described by an [RFC 6570](https://www.rfc-editor.org/rfc/rfc6570) URI template. Use it when the URI carries a variable, such as a record id.

```ts
import { ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";

server.registerResource(
{
name: "order",
template: new ResourceTemplate("orders://{orderId}", {
// List concrete resources the template can produce (or `undefined`).
list: async () => ({
resources: (await recentOrders()).map((id) => ({
name: id,
uri: `orders://${id}`,
})),
}),
// Autocomplete a template variable as the user types.
complete: {
orderId: async (value) => (await matchOrderIds(value)).slice(0, 20),
},
}),
},
async (uri, { orderId }) => ({
contents: [{ uri: uri.href, text: await renderOrder(orderId as string) }],
}),
);
```

The `list` callback is required (pass `undefined` to opt out) so a resource family is never accidentally unlistable. See [Completions](/build/resources#completions).

### `mimeType`, `title`, `description`, `_meta`

`mimeType` labels the content (`text/markdown`, `application/json`, …). `title` and `description` are the discovery surface a host shows. `_meta` carries free-form metadata, forwarded untouched.

## Handler

Runs when the resource is read. A static resource's handler receives the requested `uri`; a template's also receives the resolved template `variables`.

```ts
type ReadHandler = (
uri: URL,
variablesOrExtra: Variables | RequestHandlerExtra,
extra?: RequestHandlerExtra,
) => Promise<{
contents: Array<{
uri: string;
mimeType?: string;
text?: string; // text content
blob?: string; // base64 content
_meta?: Record<string, unknown>;
}>;
_meta?: Record<string, unknown>;
}>;
```

Return `text` for text resources or `blob` (base64) for binary. Set each entry's `uri` to `uri.href` so the response echoes the URI that was requested.

<CardGroup cols={3}>
<Card title="Register Resources" icon="file-text" href="/build/resources">
The guide, with completions
</Card>
<Card title="registerPrompt" icon="message-square" href="/api-reference/register-prompt">
Ship reusable prompts
</Card>
<Card title="McpServer" icon="server" href="/api-reference/mcp-server">
The server you register on
</Card>
</CardGroup>
78 changes: 78 additions & 0 deletions docs/build/prompts.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
---
title: "Register Prompts"
description: "Ship reusable prompts users can invoke"
icon: "message-square"
---

A **prompt** is the third MCP server primitive, alongside [tools](/build/tools) and [resources](/build/resources). It's a named, parameterized message template the user picks from the host's prompt menu; your handler returns the messages the host drops into the conversation. Use it to ship canned starting points, "Summarize this trip", "Draft a reply", so users don't retype them.

```ts server.ts
import { McpServer } from "skybridge/server";
import { z } from "zod";

const server = new McpServer({ name: "travel", version: "1.0" }).registerPrompt(
{
name: "trip-summary",
title: "Trip summary",
description: "Summarize a trip to a destination.",
argsSchema: { destination: z.string() },
},
({ destination }) => ({
messages: [
{
role: "user",
content: { type: "text", text: `Summarize a trip to ${destination}.` },
},
],
}),
);
```

[`registerPrompt`](/api-reference/register-prompt) returns the server, so it chains next to your other registrations. `argsSchema` is a [Zod](https://zod.dev/) shape: it validates the arguments the host passes and types the handler's input.

<Info>
Register prompts up front, at startup. Adding or removing them at runtime relies on `list_changed` notifications, which the stateless JSON transport can't deliver, so hosts won't see the change.
</Info>

## Completions

Wrap an argument in `completable()` to autocomplete it as the user fills in the prompt:

```ts server.ts
import { completable } from "@modelcontextprotocol/sdk/server/completable.js";
import { z } from "zod";

server.registerPrompt(
{
name: "trip-summary",
argsSchema: {
destination: completable(z.string(), async (value) =>
(await matchCities(value)).slice(0, 20),
),
},
},
({ destination }) => ({
messages: [
{
role: "user",
content: { type: "text", text: `Summarize a trip to ${destination}.` },
},
],
}),
);
```

The completion callback receives what the user has typed and returns the candidate values.

## Go Further
<Columns cols={3}>
<Card title="registerPrompt" icon="message-square" href="/api-reference/register-prompt">
Full config and handler reference
</Card>
<Card title="Register Resources" icon="file-text" href="/build/resources">
Expose readable content
</Card>
<Card title="Register Tools" icon="wrench" href="/build/tools">
The action primitive
</Card>
</Columns>
Loading
Loading