mirror of
https://github.com/shishantbiswas/bknd.git
synced 2026-03-15 20:17:22 +00:00
@@ -42,7 +42,7 @@ export const JsonViewer = ({
|
||||
copyIconProps = {},
|
||||
className,
|
||||
}: JsonViewerProps) => {
|
||||
const size = showSize ? (json === null ? 0 : JSON.stringify(json).length) : undefined;
|
||||
const size = showSize ? (!json ? 0 : JSON.stringify(json).length) : undefined;
|
||||
const formattedSize = formatNumber.fileSize(size ?? 0);
|
||||
const showContext = size || title || showCopy;
|
||||
|
||||
|
||||
@@ -218,6 +218,7 @@ const SidebarResize = ({
|
||||
|
||||
return (
|
||||
<div
|
||||
data-shell="sidebar-resize"
|
||||
data-active={isResizing ? 1 : undefined}
|
||||
className="w-px h-full hidden md:flex bg-muted after:transition-colors relative after:absolute after:inset-0 after:-left-px after:w-[2px] select-none data-[active]:after:bg-sky-400 data-[active]:cursor-col-resize hover:after:bg-sky-400 hover:cursor-col-resize after:z-2"
|
||||
onMouseDown={handleMouseDown}
|
||||
|
||||
@@ -7,8 +7,11 @@ import { useBknd } from "ui/client/bknd";
|
||||
import { Empty } from "ui/components/display/Empty";
|
||||
import { Button } from "ui/components/buttons/Button";
|
||||
import { appShellStore } from "ui/store";
|
||||
import { useBrowserTitle } from "ui/hooks/use-browser-title";
|
||||
|
||||
export default function ToolsMcp() {
|
||||
useBrowserTitle(["MCP UI"]);
|
||||
|
||||
const { config, options } = useBknd();
|
||||
const feature = useMcpStore((state) => state.feature);
|
||||
const setFeature = useMcpStore((state) => state.setFeature);
|
||||
|
||||
@@ -14,7 +14,7 @@ export const useMcpStore = create(
|
||||
content: null as ToolJson | null,
|
||||
history: [] as { type: "request" | "response"; data: any }[],
|
||||
historyLimit: 50,
|
||||
historyVisible: true,
|
||||
historyVisible: false,
|
||||
},
|
||||
(set) => ({
|
||||
setTools: (tools: ToolJson[]) => set({ tools }),
|
||||
|
||||
@@ -128,83 +128,82 @@ export function Content() {
|
||||
} catch (e) {}
|
||||
|
||||
return (
|
||||
<div className="flex flex-grow flex-col max-w-screen">
|
||||
<Form
|
||||
key={content.name}
|
||||
schema={{
|
||||
title: "InputSchema",
|
||||
...content?.inputSchema,
|
||||
}}
|
||||
validateOn="submit"
|
||||
initialValues={payload}
|
||||
hiddenSubmit={false}
|
||||
onChange={(value) => {
|
||||
setPayload(value);
|
||||
}}
|
||||
onSubmit={handleSubmit}
|
||||
>
|
||||
<AppShell.SectionHeader
|
||||
className="max-w-full min-w-0"
|
||||
right={
|
||||
<div className="flex flex-row gap-2">
|
||||
<IconButton
|
||||
Icon={historyVisible ? TbHistory : TbHistoryOff}
|
||||
onClick={() => setHistoryVisible(!historyVisible)}
|
||||
/>
|
||||
<Button
|
||||
type="submit"
|
||||
disabled={!content?.name || isPending}
|
||||
variant="primary"
|
||||
className="whitespace-nowrap"
|
||||
>
|
||||
Call Tool
|
||||
</Button>
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<AppShell.SectionHeaderTitle className="leading-tight">
|
||||
<span className="opacity-50">
|
||||
Tools <span className="opacity-70">/</span>
|
||||
</span>{" "}
|
||||
<span className="truncate">{content?.name}</span>
|
||||
</AppShell.SectionHeaderTitle>
|
||||
</AppShell.SectionHeader>
|
||||
<div className="flex flex-grow flex-row w-vw">
|
||||
<div className="flex flex-grow flex-col w-full">
|
||||
<AppShell.Scrollable>
|
||||
<div key={JSON.stringify(content)} className="flex flex-col py-4 px-5 gap-4">
|
||||
<p className="text-primary/80">{content?.description}</p>
|
||||
|
||||
{hasInputSchema && <Field name="" />}
|
||||
<JsonViewerTabs
|
||||
ref={jsonViewerTabsRef}
|
||||
expand={9}
|
||||
showCopy
|
||||
showSize
|
||||
tabs={{
|
||||
Arguments: {
|
||||
json: payload,
|
||||
title: "Payload",
|
||||
enabled: hasInputSchema,
|
||||
},
|
||||
Result: { json: readableResult, title: "Result" },
|
||||
Configuration: {
|
||||
json: content ?? null,
|
||||
title: "Configuration",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</AppShell.Scrollable>
|
||||
<Form
|
||||
className="flex flex-grow flex-col max-w-screen"
|
||||
key={content.name}
|
||||
schema={{
|
||||
title: "InputSchema",
|
||||
...content?.inputSchema,
|
||||
}}
|
||||
validateOn="submit"
|
||||
initialValues={payload}
|
||||
hiddenSubmit={false}
|
||||
onChange={(value) => {
|
||||
setPayload(value);
|
||||
}}
|
||||
onSubmit={handleSubmit}
|
||||
>
|
||||
<AppShell.SectionHeader
|
||||
className="max-w-full min-w-0"
|
||||
right={
|
||||
<div className="flex flex-row gap-2">
|
||||
<IconButton
|
||||
Icon={historyVisible ? TbHistory : TbHistoryOff}
|
||||
onClick={() => setHistoryVisible(!historyVisible)}
|
||||
/>
|
||||
<Button
|
||||
type="submit"
|
||||
disabled={!content?.name || isPending}
|
||||
variant="primary"
|
||||
className="whitespace-nowrap"
|
||||
>
|
||||
Call Tool
|
||||
</Button>
|
||||
</div>
|
||||
{historyVisible && (
|
||||
<AppShell.Sidebar name="right" handle="left" maxWidth={window.innerWidth * 0.4}>
|
||||
<History />
|
||||
</AppShell.Sidebar>
|
||||
)}
|
||||
}
|
||||
>
|
||||
<AppShell.SectionHeaderTitle className="leading-tight">
|
||||
<span className="opacity-50">
|
||||
Tools <span className="opacity-70">/</span>
|
||||
</span>{" "}
|
||||
<span className="truncate">{content?.name}</span>
|
||||
</AppShell.SectionHeaderTitle>
|
||||
</AppShell.SectionHeader>
|
||||
<div className="flex flex-grow flex-row w-vw">
|
||||
<div className="flex flex-grow flex-col w-full">
|
||||
<AppShell.Scrollable>
|
||||
<div key={JSON.stringify(content)} className="flex flex-col py-4 px-5 gap-4">
|
||||
<p className="text-primary/80">{content?.description}</p>
|
||||
|
||||
{hasInputSchema && <Field name="" />}
|
||||
<JsonViewerTabs
|
||||
ref={jsonViewerTabsRef}
|
||||
expand={9}
|
||||
showCopy
|
||||
showSize
|
||||
tabs={{
|
||||
Arguments: {
|
||||
json: payload,
|
||||
title: "Payload",
|
||||
enabled: hasInputSchema,
|
||||
},
|
||||
Result: { json: readableResult, title: "Result" },
|
||||
Configuration: {
|
||||
json: content ?? null,
|
||||
title: "Configuration",
|
||||
},
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</AppShell.Scrollable>
|
||||
</div>
|
||||
</Form>
|
||||
</div>
|
||||
{historyVisible && (
|
||||
<AppShell.Sidebar name="right" handle="left" maxWidth={window.innerWidth * 0.4}>
|
||||
<History />
|
||||
</AppShell.Sidebar>
|
||||
)}
|
||||
</div>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,29 @@ export function McpTool({ tool }: { tool: ReturnType<Tool["toJSON"]> }) {
|
||||
);
|
||||
}
|
||||
|
||||
const getType = (value: JSONSchemaDefinition) => {
|
||||
if (value === undefined || value === null) {
|
||||
return "any";
|
||||
}
|
||||
|
||||
if (value.type) {
|
||||
if (Array.isArray(value.type)) {
|
||||
return value.type.join(" | ");
|
||||
}
|
||||
return value.type;
|
||||
}
|
||||
|
||||
if ("anyOf" in value) {
|
||||
return value.anyOf.map(getType).join(" | ");
|
||||
}
|
||||
|
||||
if ("oneOf" in value) {
|
||||
return value.oneOf.map(getType).join(" | ");
|
||||
}
|
||||
|
||||
return "any";
|
||||
};
|
||||
|
||||
export function JsonSchemaTypeTable({ schema }: { schema: JSONSchemaDefinition }) {
|
||||
const properties = schema.properties ?? {};
|
||||
const required = schema.required ?? [];
|
||||
@@ -44,8 +67,8 @@ export function JsonSchemaTypeTable({ schema }: { schema: JSONSchemaDefinition }
|
||||
typeDescription: (
|
||||
<DynamicCodeBlock lang="json" code={indent(getTypeDescription(value), 1)} />
|
||||
),
|
||||
type: value.type,
|
||||
default: value.default ? JSON.stringify(value.default) : undefined,
|
||||
type: getType(value),
|
||||
default: value.default !== undefined ? JSON.stringify(value.default) : undefined,
|
||||
required: required.includes(key),
|
||||
},
|
||||
]),
|
||||
|
||||
16
docs/components/misc/Wrapper.tsx
Normal file
16
docs/components/misc/Wrapper.tsx
Normal file
@@ -0,0 +1,16 @@
|
||||
import { cn } from "@/lib/cn";
|
||||
import type { HTMLAttributes } from "react";
|
||||
|
||||
export function Wrapper(props: HTMLAttributes<HTMLDivElement>) {
|
||||
return (
|
||||
<div
|
||||
{...props}
|
||||
className={cn(
|
||||
"rounded-lg bg-radial-[at_bottom] from-fd-primary/10 p-4 border bg-origin-border border-fd-accent-primary/10 prose-no-margin dark:bg-black/20",
|
||||
props.className,
|
||||
)}
|
||||
>
|
||||
{props.children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -15,6 +15,7 @@
|
||||
"./usage/sdk",
|
||||
"./usage/react",
|
||||
"./usage/elements",
|
||||
"./usage/mcp/",
|
||||
"---Extending---",
|
||||
"./extending/config",
|
||||
"./extending/events",
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"pages": ["overview", "mcp"]
|
||||
}
|
||||
4
docs/content/docs/(documentation)/usage/mcp/meta.json
Normal file
4
docs/content/docs/(documentation)/usage/mcp/meta.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"title": "MCP",
|
||||
"pages": ["overview", "tools-resources"]
|
||||
}
|
||||
208
docs/content/docs/(documentation)/usage/mcp/overview.mdx
Normal file
208
docs/content/docs/(documentation)/usage/mcp/overview.mdx
Normal file
@@ -0,0 +1,208 @@
|
||||
---
|
||||
title: "Overview"
|
||||
description: "Built-in full featured MCP server."
|
||||
tags: ["documentation"]
|
||||
---
|
||||
import { ImageZoom } from "fumadocs-ui/components/image-zoom";
|
||||
import { Accordion, Accordions } from 'fumadocs-ui/components/accordion';
|
||||
|
||||
|
||||
<Callout type="warning">
|
||||
The MCP server is currently experimental and may change in the future. During this period, it is disabled by default. To stabilize it, and make **bknd MCP native**, all configuration changes you can make today with the integrated Admin UI will be migrated to use the MCP server.
|
||||
</Callout>
|
||||
|
||||
bknd includes a fully featured MCP server that can be used to interact with the bknd instance. It uses a lightweight MCP implementation that works in any environment bknd works in. Unlike other MCP servers, the exposed tools and resources are mainly dynamically generated from the schema, extracted from defined hono routes, and manually defined ones. This means exposed tools and resources are always up to date, and requires little overhead to maintain.
|
||||
|
||||
- Fully featured, always up to date MCP server natively integrated with bknd
|
||||
- Integrated MCP UI accessible from the Admin UI
|
||||
- Built-in MCP client directly usable from your app instance
|
||||
- CLI command to run an MCP server on stdio transport
|
||||
|
||||
|
||||
## Integrated MCP UI
|
||||
<video controls poster="/content/mcp/v0.17_mcp_o_frame_12.5s.jpg">
|
||||
<source src="/content/mcp/v0.17_mcp_o.mp4" type="video/mp4" />
|
||||
</video>
|
||||
|
||||
Once enabled, you can access the MCP UI at `/mcp` or choose "MCP" from the top right user menu.
|
||||
|
||||
## Enable MCP
|
||||
|
||||
If you're using `initialConfig`, you can enable the MCP server by setting the `server.mcp.enabled` property to `true`.
|
||||
|
||||
```typescript
|
||||
import type { BkndConfig } from "bknd";
|
||||
|
||||
export default {
|
||||
initialConfig: {
|
||||
server: {
|
||||
mcp: {
|
||||
enabled: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
} satisfies BkndConfig;
|
||||
```
|
||||
|
||||
Using the Admin UI, you can either navigate to `/settings/server` or click top right on the user menu, select "Settings", then "Server". Enable the MCP server by checking the "Enabled" checkbox under "Mcp".
|
||||
|
||||
## Using the MCP Client
|
||||
|
||||
The implementation is closely following the [MCP spec 2025-06-18](https://modelcontextprotocol.io/specification/2025-06-18) powered by [jsonv-ts](https://github.com/jsonv-ts/jsonv-ts), therefore any spec compliant client will work. However, there is a built-in MCP client:
|
||||
|
||||
```typescript
|
||||
import { McpClient } from "bknd/utils";
|
||||
|
||||
const client = new McpClient({
|
||||
url: "http://localhost:1337/mcp",
|
||||
});
|
||||
```
|
||||
|
||||
Alternatively, similar to the `getApi` function, you can use the `getMcpClient` function to get the client from your app instance that doesn't travel through the network.
|
||||
|
||||
```typescript
|
||||
import { createApp } from "bknd";
|
||||
|
||||
const app = createApp();
|
||||
const client = app.getMcpClient();
|
||||
```
|
||||
|
||||
Unlike the official spec requires, there is no initialization required, but supported. Without connecting, initialization or fetching the list of tools, you can directly call them. For example, you could fetch a list of `posts`:
|
||||
|
||||
```typescript
|
||||
const result = await client.callTool({
|
||||
name: "data_entity_read_many",
|
||||
arguments: {
|
||||
entity: "posts",
|
||||
limit: 3,
|
||||
select: ["id", "title"],
|
||||
},
|
||||
});
|
||||
// {
|
||||
// data: [
|
||||
// { id: 1, title: "Post 1" },
|
||||
// { id: 2, title: "Post 2" },
|
||||
// { id: 3, title: "Post 3" }
|
||||
// ],
|
||||
// }
|
||||
```
|
||||
|
||||
Refer to the [jsonv-ts docs](https://github.com/dswbx/jsonv-ts#mcp-client) for more information.
|
||||
|
||||
## STDIO Transport
|
||||
|
||||
To start an MCP server on stdio transport, you can use the `mcp` CLI command. This is useful when you want to use it with IDEs or other tools that support stdio transport.
|
||||
|
||||
```bash
|
||||
npx bknd mcp
|
||||
```
|
||||
|
||||
If you want have the Streamable HTTP endpoint disabled, you can still use the STDIO transport by passing the `--force` option.
|
||||
|
||||
```bash
|
||||
npx bknd mcp --force
|
||||
```
|
||||
|
||||
## Usage in external tools
|
||||
|
||||
You can also use the MCP server in external tools, such as VS Code, Cursor, or other IDEs that support MCP. This list is not exhaustive, and will be updated.
|
||||
|
||||
<Accordions type="single">
|
||||
<Accordion title="Cursor">
|
||||
Go to: `Settings` -> `Cursor Settings` -> `Tools & Integrations` -> `Add a custom MCP server`
|
||||
|
||||
Pasting the following config into your Cursor `~/.cursor/mcp.json` file is the recommended approach. You can also install in a specific project by creating `.cursor/mcp.json` in your project folder. See [Cursor MCP docs](https://docs.cursor.com/context/model-context-protocol) for more info.
|
||||
|
||||
```json tab="Local"
|
||||
{
|
||||
"mcpServers": {
|
||||
"bknd": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "bknd@latest", "mcp"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```json tab="Remote"
|
||||
{
|
||||
"mcpServers": {
|
||||
"bknd": {
|
||||
"url": "http://localhost:1337/mcp"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="VS Code">
|
||||
Add this to your VS Code MCP config. See [VS Code MCP docs](https://code.visualstudio.com/docs/copilot/chat/mcp-servers) for more info.
|
||||
|
||||
```json tab="Local"
|
||||
{
|
||||
"servers": {
|
||||
"bknd": {
|
||||
"type": "stdio",
|
||||
"command": "npx",
|
||||
"args": ["-y", "bknd@latest", "mcp"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```json tab="Remote"
|
||||
{
|
||||
"servers": {
|
||||
"bknd": {
|
||||
"type": "http",
|
||||
"url": "http://localhost:1337/mcp"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Claude Desktop">
|
||||
Add this to your Claude Desktop `claude_desktop_config.json` file. See [Claude Desktop MCP docs](https://modelcontextprotocol.io/quickstart/user) for more info.
|
||||
|
||||
```json title="claude_desktop_config.json"
|
||||
{
|
||||
"mcpServers": {
|
||||
"bknd": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "bknd@latest", "mcp"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
</Accordion>
|
||||
</Accordions>
|
||||
|
||||
If a tool you're using is not listed here, please let us know by [opening an issue](https://github.com/bknd-dev/bknd/issues/new) or [contacting us on Discord](https://discord.com/invite/Qjz9nNHYTB).
|
||||
|
||||
## Authentication
|
||||
|
||||
Both the Streamable HTTP and STDIO transport support authentication. The same authentication mechanism as the API is used, so permissions work the exact same way.
|
||||
|
||||
When using the Streamable HTTP transport, you can pass the `Authorization` header to the client.
|
||||
|
||||
```typescript
|
||||
const client = new McpClient({
|
||||
url: "http://localhost:1337/mcp",
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
When using the STDIO transport, you can pass an `--token` option to the CLI command.
|
||||
|
||||
```bash
|
||||
npx bknd mcp --token <token>
|
||||
```
|
||||
|
||||
Alternatively, you can also use the `BEARER_TOKEN` environment variable.
|
||||
|
||||
```bash
|
||||
BEARER_TOKEN=<token> npx bknd mcp
|
||||
```
|
||||
File diff suppressed because one or more lines are too long
1954
docs/mcp.json
1954
docs/mcp.json
File diff suppressed because it is too large
Load Diff
@@ -5,11 +5,12 @@ import type { MDXComponents } from "mdx/types";
|
||||
import * as FilesComponents from "fumadocs-ui/components/files";
|
||||
import * as TabsComponents from "fumadocs-ui/components/tabs";
|
||||
import { Accordion, Accordions } from "fumadocs-ui/components/accordion";
|
||||
import { ImageZoom } from "fumadocs-ui/components/image-zoom";
|
||||
import {
|
||||
CalloutInfo,
|
||||
CalloutPositive,
|
||||
CalloutCaution,
|
||||
CalloutDanger,
|
||||
CalloutInfo,
|
||||
CalloutPositive,
|
||||
CalloutCaution,
|
||||
CalloutDanger,
|
||||
} from "./app/_components/Callout";
|
||||
import { StackBlitz } from "./app/_components/StackBlitz";
|
||||
import { Icon } from "@iconify/react";
|
||||
@@ -18,29 +19,30 @@ import * as Twoslash from "fumadocs-twoslash/ui";
|
||||
|
||||
import { createGenerator } from "fumadocs-typescript";
|
||||
import { AutoTypeTable } from "fumadocs-typescript/ui";
|
||||
import { Wrapper } from "@/components/misc/Wrapper";
|
||||
|
||||
const generator = createGenerator({
|
||||
tsconfigPath: "../tsconfig.json",
|
||||
tsconfigPath: "../tsconfig.json",
|
||||
});
|
||||
|
||||
export function getMDXComponents(components?: MDXComponents): MDXComponents {
|
||||
return {
|
||||
...defaultMdxComponents,
|
||||
...TabsComponents,
|
||||
...FilesComponents,
|
||||
...Twoslash,
|
||||
Accordion,
|
||||
Accordions,
|
||||
CalloutInfo,
|
||||
CalloutPositive,
|
||||
CalloutCaution,
|
||||
CalloutDanger,
|
||||
StackBlitz,
|
||||
Icon,
|
||||
APIPage: (props) => <APIPage {...openapi.getAPIPageProps(props)} />,
|
||||
AutoTypeTable: (props) => (
|
||||
<AutoTypeTable {...props} generator={generator} />
|
||||
),
|
||||
...components,
|
||||
};
|
||||
return {
|
||||
...defaultMdxComponents,
|
||||
...TabsComponents,
|
||||
...FilesComponents,
|
||||
...Twoslash,
|
||||
Accordion,
|
||||
Accordions,
|
||||
CalloutInfo,
|
||||
CalloutPositive,
|
||||
CalloutCaution,
|
||||
CalloutDanger,
|
||||
StackBlitz,
|
||||
Icon,
|
||||
Wrapper,
|
||||
img: (props) => <ImageZoom {...(props as any)} />,
|
||||
APIPage: (props) => <APIPage {...openapi.getAPIPageProps(props)} />,
|
||||
AutoTypeTable: (props) => <AutoTypeTable {...props} generator={generator} />,
|
||||
...components,
|
||||
};
|
||||
}
|
||||
|
||||
BIN
docs/public/content/mcp/bknd_mcp_ui.png
Normal file
BIN
docs/public/content/mcp/bknd_mcp_ui.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 100 KiB |
BIN
docs/public/content/mcp/v0.17_mcp_o.mp4
Normal file
BIN
docs/public/content/mcp/v0.17_mcp_o.mp4
Normal file
Binary file not shown.
BIN
docs/public/content/mcp/v0.17_mcp_o_frame_12.5s.jpg
Normal file
BIN
docs/public/content/mcp/v0.17_mcp_o_frame_12.5s.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 106 KiB |
@@ -6,18 +6,12 @@ import { writeFile, readFile } from "node:fs/promises";
|
||||
|
||||
const config = {
|
||||
mcpConfig: "./mcp.json",
|
||||
outFile: "./content/docs/(documentation)/modules/server/mcp.mdx",
|
||||
outFile: "./content/docs/(documentation)/usage/mcp/tools-resources.mdx",
|
||||
};
|
||||
|
||||
async function generate() {
|
||||
console.info("Generating MCP documentation...");
|
||||
|
||||
try {
|
||||
console.log("bun version", Bun.version);
|
||||
} catch (e) {
|
||||
console.log("bun failed");
|
||||
}
|
||||
|
||||
await cleanup();
|
||||
const mcpConfig = JSON.parse(await readFile(config.mcpConfig, "utf-8"));
|
||||
const document = await generateDocument(mcpConfig);
|
||||
@@ -34,7 +28,7 @@ async function generateDocument({
|
||||
}) {
|
||||
return `---
|
||||
title: "MCP"
|
||||
description: "Built-in full featured MCP server."
|
||||
description: "Tools & Resources of the built-in full featured MCP server."
|
||||
tags: ["documentation"]
|
||||
---
|
||||
import { JsonSchemaTypeTable } from '@/components/McpTool';
|
||||
|
||||
Reference in New Issue
Block a user