Skip to content
Merged
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
12 changes: 11 additions & 1 deletion mcp-docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export default defineConfig({
description: MCP_DOCS_DESCRIPTION,
/** README is contributor-facing only — keep it out of the built site + sitemap. */
srcExclude: ['README.md'],
lastUpdated: true,
head: [
['script', {}, 'document.documentElement.classList.add("fyp-site-mcp")'],
['meta', { name: 'twitter:card', content: 'summary_large_image' }],
Expand Down Expand Up @@ -87,6 +88,7 @@ export default defineConfig({
{ text: 'What you can ask', link: '/use/capabilities' },
{ text: 'Limits', link: '/use/guarantees' },
{ text: 'Pricing', link: '/use/pricing' },
{ text: 'Terms', link: '/use/terms' },
{
text: 'Reference',
collapsed: true,
Expand Down Expand Up @@ -134,10 +136,18 @@ export default defineConfig({
search: {
provider: 'local',
},
editLink: {
pattern: 'https://github.com/feelyourprotocol/website/edit/main/mcp-docs/:path',
text: 'Edit this page on GitHub',
},
docFooter: {
prev: 'Previous',
next: 'Next',
},
footer: {
message:
'Get started = connect and ask questions. Reference = catalogues and tool schemas. Internals = for builders.',
copyright: 'Feel Your Protocol',
copyright: 'Feel Your Protocol · <a href="/use/terms.html">Terms</a>',
},
},
})
36 changes: 36 additions & 0 deletions mcp-docs/.vitepress/theme/__tests__/mcpConstants.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { describe, expect, it } from 'vitest'

import {
CLAUDE_CODE_ADD_COMMAND,
CODEX_ADD_COMMAND,
CODEX_CONFIG_TOML,
CURSOR_INSTALL_LINK,
cursorMcpInstallLink,
FYP_MCP_URL,
} from '../mcpConstants'

describe('mcpConstants', () => {
it('builds a Cursor install deeplink whose config decodes to the server entry', () => {
const link = cursorMcpInstallLink('feel-your-protocol', { url: FYP_MCP_URL })
expect(link.startsWith('cursor://anysphere.cursor-deeplink/mcp/install?')).toBe(true)
const params = new URL(link.replace('cursor://', 'https://')).searchParams
expect(params.get('name')).toBe('feel-your-protocol')
const decoded = JSON.parse(Buffer.from(params.get('config') ?? '', 'base64').toString('utf8'))
expect(decoded).toEqual({ url: FYP_MCP_URL })
expect(CURSOR_INSTALL_LINK).toBe(link)
})

it('encodes unusual server names safely', () => {
const link = cursorMcpInstallLink('a b&c', { url: FYP_MCP_URL })
expect(link).toContain('name=a%20b%26c')
})

it('uses the documented Claude Code and Codex forms', () => {
expect(CLAUDE_CODE_ADD_COMMAND).toBe(
`claude mcp add --transport http feel-your-protocol ${FYP_MCP_URL}`,
)
expect(CODEX_ADD_COMMAND).toBe(`codex mcp add feel-your-protocol --url ${FYP_MCP_URL}`)
expect(CODEX_CONFIG_TOML).toContain('[mcp_servers.feel-your-protocol]')
expect(CODEX_CONFIG_TOML).toContain(`url = "${FYP_MCP_URL}"`)
})
})
145 changes: 145 additions & 0 deletions mcp-docs/.vitepress/theme/components/ClientTabs.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
<script setup lang="ts">
import { ref } from 'vue'

import {
CLAUDE_CODE_ADD_COMMAND,
CODEX_ADD_COMMAND,
CODEX_CONFIG_TOML,
CURSOR_INSTALL_LINK,
CURSOR_MCP_JSON,
FYP_MCP_URL,
} from '../mcpConstants'
import CodeSnippet from './CodeSnippet.vue'

type TabId = 'cursor' | 'claude' | 'codex' | 'other'

const tabs: { id: TabId; label: string }[] = [
{ id: 'cursor', label: 'Cursor' },
{ id: 'claude', label: 'Claude' },
{ id: 'codex', label: 'Codex' },
{ id: 'other', label: 'Other hosts' },
]

const active = ref<TabId>('cursor')
</script>

<template>
<div class="fyp-client-tabs" data-testid="client-tabs">
<div class="fyp-client-tabs__list" role="tablist" aria-label="MCP client setup">
<button
v-for="tab in tabs"
:id="`fyp-tab-${tab.id}`"
:key="tab.id"
type="button"
role="tab"
class="fyp-client-tabs__tab"
:class="{ 'fyp-client-tabs__tab--active': active === tab.id }"
:aria-selected="active === tab.id"
:aria-controls="`fyp-panel-${tab.id}`"
@click="active = tab.id"
>
{{ tab.label }}
</button>
</div>

<div
v-show="active === 'cursor'"
id="fyp-panel-cursor"
class="fyp-client-tabs__panel"
role="tabpanel"
aria-labelledby="fyp-tab-cursor"
>
<p>
<a class="fyp-install-link" :href="CURSOR_INSTALL_LINK">Add to Cursor</a>
</p>
<p class="fyp-client-tabs__note">
Opens Cursor and asks before installing. Prefer to edit the file yourself? Add this to your user
<code>mcp.json</code> (Cursor Settings → MCP):
</p>
<CodeSnippet :code="CURSOR_MCP_JSON" language="json" />
<p class="fyp-client-tabs__note">
Then restart Cursor or reload MCP servers. You should see six tools. Remote HTTP MCP needs a recent
Cursor build.
</p>
</div>

<div
v-show="active === 'claude'"
id="fyp-panel-claude"
class="fyp-client-tabs__panel"
role="tabpanel"
aria-labelledby="fyp-tab-claude"
>
<p><strong>Claude Code</strong> — one command:</p>
<CodeSnippet :code="CLAUDE_CODE_ADD_COMMAND" language="bash" />
<p>
<strong>Claude Desktop and claude.ai</strong> — add the server as a custom connector, not in the config
file:
</p>
<ol class="fyp-client-tabs__steps">
<li>Open <strong>Customize → Connectors</strong> and choose <strong>Add custom connector</strong>.</li>
<li>Name it <code>feel-your-protocol</code> and paste the URL below.</li>
<li>Leave authentication empty — the server needs no key.</li>
</ol>
<CodeSnippet :code="FYP_MCP_URL" language="url" />
<p class="fyp-client-tabs__note">
Claude connects to remote servers from Anthropic’s cloud, and custom connectors depend on your plan.
Do not put a <code>url</code> entry into <code>claude_desktop_config.json</code> — that file is for
local servers only.
</p>
</div>

<div
v-show="active === 'codex'"
id="fyp-panel-codex"
class="fyp-client-tabs__panel"
role="tabpanel"
aria-labelledby="fyp-tab-codex"
>
<p>One command (works for the Codex CLI, IDE extension, and desktop app, which share config):</p>
<CodeSnippet :code="CODEX_ADD_COMMAND" language="bash" />
<p class="fyp-client-tabs__note">
Or add this to <code>~/.codex/config.toml</code> (or a trusted project’s
<code>.codex/config.toml</code>):
</p>
<CodeSnippet :code="CODEX_CONFIG_TOML" language="toml" />
</div>

<div
v-show="active === 'other'"
id="fyp-panel-other"
class="fyp-client-tabs__panel"
role="tabpanel"
aria-labelledby="fyp-tab-other"
>
<p>Any host that supports remote MCP over HTTP can use these values:</p>
<table class="fyp-client-tabs__table">
<thead>
<tr>
<th>Field</th>
<th>Value</th>
</tr>
</thead>
<tbody>
<tr>
<td>URL</td>
<td>
<code>{{ FYP_MCP_URL }}</code>
</td>
</tr>
<tr>
<td>Transport</td>
<td>Streamable HTTP</td>
</tr>
<tr>
<td>Auth at launch</td>
<td>none</td>
</tr>
</tbody>
</table>
<p class="fyp-client-tabs__note">
Config formats differ per host, so check your client’s MCP documentation for where these go.
</p>
</div>
</div>
</template>
20 changes: 20 additions & 0 deletions mcp-docs/.vitepress/theme/components/CodeSnippet.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<script setup lang="ts">
import CopyButton from './CopyButton.vue'

defineProps<{
code: string
language?: string
caption?: string
}>()
</script>

<template>
<figure class="fyp-code-snippet" data-testid="code-snippet">
<figcaption v-if="caption" class="fyp-code-snippet__caption">{{ caption }}</figcaption>
<div class="fyp-code-snippet__bar">
<span class="fyp-code-snippet__lang">{{ language ?? '' }}</span>
<CopyButton :text="code" />
</div>
<pre class="fyp-code-snippet__pre"><code>{{ code }}</code></pre>
</figure>
</template>
22 changes: 22 additions & 0 deletions mcp-docs/.vitepress/theme/components/CollapsibleChangelog.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<script setup lang="ts">
import Changelog from './Changelog.vue'

interface ChangelogEntry {
version: string
date?: string
summary: string
}

defineProps<{
entries: ChangelogEntry[]
title?: string
open?: boolean
}>()
</script>

<template>
<details class="fyp-changelog-collapse" data-testid="collapsible-changelog" :open="open">
<summary class="fyp-changelog-collapse__summary">{{ title ?? 'Section changelog' }}</summary>
<Changelog :entries="entries" :title="title" />
</details>
</template>
27 changes: 27 additions & 0 deletions mcp-docs/.vitepress/theme/components/CopyButton.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<script setup lang="ts">
import { useCopy } from '../composables/useCopy'

const props = withDefaults(
defineProps<{
text: string
label?: string
copiedLabel?: string
}>(),
{ label: 'Copy', copiedLabel: 'Copied' },
)

const { copied, copy } = useCopy()
</script>

<template>
<button
type="button"
class="fyp-copy-btn"
:class="{ 'fyp-copy-btn--done': copied }"
data-testid="copy-button"
:aria-label="copied ? props.copiedLabel : `${props.label} to clipboard`"
@click="copy(props.text)"
>
{{ copied ? props.copiedLabel : props.label }}
</button>
</template>
20 changes: 20 additions & 0 deletions mcp-docs/.vitepress/theme/components/DoorStrip.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<script setup lang="ts">
export interface DoorItem {
title: string
detail: string
href: string
}

defineProps<{
items: DoorItem[]
}>()
</script>

<template>
<nav class="fyp-door-strip" aria-label="Documentation sections" data-testid="door-strip">
<a v-for="item in items" :key="item.href" class="fyp-door-strip__item" :href="item.href">
<span class="fyp-door-strip__title">{{ item.title }}</span>
<span class="fyp-door-strip__detail">{{ item.detail }}</span>
</a>
</nav>
</template>
48 changes: 48 additions & 0 deletions mcp-docs/.vitepress/theme/components/EipHeader.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<script setup lang="ts">
import { TOOL_DOC_PATH } from '../mcpConstants'

defineProps<{
number: number | string
title: string
status?: 'Runnable' | 'Planned'
fork?: string
tools?: string[]
launchNote?: string
explorationHref?: string
explorationLabel?: string
}>()
</script>

<template>
<header class="fyp-eip-header" data-testid="eip-header">
<div class="fyp-eip-header__row">
<p class="fyp-eip-header__id">
<span class="fyp-eip-header__number">EIP-{{ number }}</span>
<span class="fyp-eip-header__title">{{ title }}</span>
</p>
<span v-if="status" class="fyp-chip fyp-chip--status">{{ status }}</span>
</div>
<p v-if="launchNote" class="fyp-eip-header__launch">{{ launchNote }}</p>
<div class="fyp-eip-header__chips">
<span v-if="fork" class="fyp-chip fyp-chip--fork">{{ fork }}</span>
<template v-if="tools?.length">
<span class="fyp-eip-header__tools-label">Runs with</span>
<component
:is="TOOL_DOC_PATH[tool] ? 'a' : 'span'"
v-for="tool in tools"
:key="tool"
class="fyp-chip fyp-chip--tool"
:href="TOOL_DOC_PATH[tool]"
>
{{ tool }}
</component>
</template>
</div>
<p v-if="explorationHref" class="fyp-eip-header__links">
Website twin:
<a :href="explorationHref" target="_blank" rel="noopener noreferrer">
{{ explorationLabel ?? 'exploration on feelyourprotocol.org' }}
</a>
</p>
</header>
</template>
18 changes: 18 additions & 0 deletions mcp-docs/.vitepress/theme/components/EndpointCard.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<script setup lang="ts">
import { FYP_MCP_URL } from '../mcpConstants'
import CopyButton from './CopyButton.vue'

defineProps<{
label?: string
}>()
</script>

<template>
<div class="fyp-endpoint-card" data-testid="endpoint-card">
<p class="fyp-endpoint-card__label">{{ label ?? 'Endpoint (at launch)' }}</p>
<div class="fyp-endpoint-card__row">
<code class="fyp-endpoint-card__url">{{ FYP_MCP_URL }}</code>
<CopyButton :text="FYP_MCP_URL" label="Copy URL" />
</div>
</div>
</template>
Loading
Loading