better vscode integration
This commit is contained in:
@@ -16,7 +16,32 @@ Copilot interacts with MCP servers through independently exposed lanes:
|
|||||||
2. resources attached as read-only context
|
2. resources attached as read-only context
|
||||||
3. server-provided prompts
|
3. server-provided prompts
|
||||||
|
|
||||||
This server publishes skills as native `skill://` resources and prompts as native MCP prompt objects.
|
This server publishes skills as native `skill://` resources and prompts as native MCP prompt objects. It also exposes generic `list_resources` and `read_resource` tools for agents whose tool catalog does not include direct MCP resource operations.
|
||||||
|
|
||||||
|
## VS Code Feature Coverage
|
||||||
|
|
||||||
|
The server uses every FastMCP feature that applies to its read-only guidance workload:
|
||||||
|
|
||||||
|
| Feature | Usage |
|
||||||
|
| --- | --- |
|
||||||
|
| Server identity | The initialize response includes a stable name, usage instructions, and a self-contained icon for VS Code's MCP server UI. |
|
||||||
|
| Tools | Compatibility tools have display titles, structured output schemas, and read-only, idempotent, closed-world annotations. FastMCP's default schema dereferencing remains enabled for clients such as VS Code that require flat schemas. |
|
||||||
|
| Resources | Documentation and skills use native resources and wildcard resource templates with explicit Markdown MIME types. |
|
||||||
|
| Prompts | Declarative workflows use native prompt objects with descriptions, display titles, typed arguments, and slash-command access. |
|
||||||
|
| Argument completion | Prompt arguments with authored `choices` are returned through `completion/complete` as the user types. |
|
||||||
|
|
||||||
|
[FastMCP server identity](https://gofastmcp.com/servers/server), [component icons](https://gofastmcp.com/servers/icons), [tool metadata](https://gofastmcp.com/servers/tools), and [argument completion](https://gofastmcp.com/servers/completions) define the implementation details. [VS Code's MCP documentation](https://code.visualstudio.com/docs/agent-customization/mcp-servers) describes how tools, resources, prompts, and MCP Apps appear in the client.
|
||||||
|
|
||||||
|
The following capabilities are conditional rather than useful by default:
|
||||||
|
|
||||||
|
1. MCP Apps require an interactive tool result such as a form or visualization; this server returns guidance and structured resource data only.
|
||||||
|
2. Sampling is appropriate only when server-side work must ask VS Code to run an LLM. The current server retrieves authored content and does not generate it.
|
||||||
|
3. Elicitation is appropriate only when a running operation needs additional user input. Prompt arguments already collect all required input before execution.
|
||||||
|
4. Progress, client logging, and background tasks require long-running operations. Current reads and prompt rendering are bounded local operations.
|
||||||
|
5. Client roots matter only when server behavior depends on client filesystem roots. This server reads packaged content and never traverses a client workspace.
|
||||||
|
6. `website_url` requires a canonical public deployment URL. None is configured, so the server does not advertise a guessed address.
|
||||||
|
|
||||||
|
Add one of these capabilities when a concrete workflow needs it, then cover its negotiated capability and protocol response in the HTTP MCP smoke tests. See the [FastMCP Apps overview](https://gofastmcp.com/apps/overview), [sampling](https://gofastmcp.com/servers/sampling), [elicitation](https://gofastmcp.com/servers/elicitation), [progress reporting](https://gofastmcp.com/servers/progress), and [MCP context](https://gofastmcp.com/servers/context) for the activation criteria.
|
||||||
|
|
||||||
## Native Skill Resources
|
## Native Skill Resources
|
||||||
|
|
||||||
@@ -26,7 +51,7 @@ For every skill, Copilot can discover:
|
|||||||
2. `skill://<name>/_manifest`
|
2. `skill://<name>/_manifest`
|
||||||
3. `skill://<name>/{path*}` supporting-file template
|
3. `skill://<name>/{path*}` supporting-file template
|
||||||
|
|
||||||
The main resource description comes from `SKILL.md`. The manifest discloses supporting paths, sizes, and SHA256 hashes. This is the only skill discovery contract; there is no parallel skill catalog.
|
The main resource description comes from `SKILL.md`. The manifest discloses supporting paths, sizes, and SHA256 hashes. Native resources remain the only skill content and discovery contract; the generic tools delegate to that same resource surface rather than maintaining a parallel catalog.
|
||||||
|
|
||||||
## Resource Picker Availability
|
## Resource Picker Availability
|
||||||
|
|
||||||
@@ -39,10 +64,15 @@ A successful `resources/list` response does not guarantee the picker appears in
|
|||||||
|
|
||||||
## Recommended Workflow
|
## Recommended Workflow
|
||||||
|
|
||||||
1. browse the server's resources
|
For autonomous agents:
|
||||||
2. attach one relevant `skill://<name>/SKILL.md`
|
|
||||||
3. attach `_manifest` only if supporting detail may be needed
|
1. call `list_resources`
|
||||||
4. attach only selected supporting files
|
2. compare main skill names and descriptions
|
||||||
|
3. call `read_resource` for one relevant `skill://<name>/SKILL.md`
|
||||||
|
4. read `_manifest` only if supporting detail may be needed
|
||||||
|
5. read only selected supporting files
|
||||||
|
|
||||||
|
For manual context attachment, browse the server's resources and attach the same bounded set of files.
|
||||||
|
|
||||||
## Prompt Examples
|
## Prompt Examples
|
||||||
|
|
||||||
@@ -72,13 +102,13 @@ A repo-level instruction should name the native retrieval order and context budg
|
|||||||
When a task matches a personal-mcp skill:
|
When a task matches a personal-mcp skill:
|
||||||
|
|
||||||
1. Prefer an already attached native skill resource.
|
1. Prefer an already attached native skill resource.
|
||||||
2. Otherwise browse MCP resources and select one `skill://<name>/SKILL.md` resource by description.
|
2. Otherwise call `list_resources` and select one `skill://<name>/SKILL.md` resource by description.
|
||||||
3. Read `_manifest` only when supporting material is needed.
|
3. Call `read_resource` for the selected skill and read `_manifest` only when supporting material is needed.
|
||||||
4. Load at most two candidate main files and only the relevant supporting paths.
|
4. Load at most two candidate main files and only the relevant supporting paths.
|
||||||
5. Reconcile guidance with the current repository before editing.
|
5. Reconcile guidance with the current repository before editing.
|
||||||
```
|
```
|
||||||
|
|
||||||
Instructions steer behavior but do not force VS Code to attach resources automatically.
|
Instructions steer behavior but do not force VS Code to attach resources automatically. The generic tools provide an agent-callable fallback when direct resource operations are absent from the deferred-tool catalog.
|
||||||
|
|
||||||
## Prompt Objects
|
## Prompt Objects
|
||||||
|
|
||||||
@@ -88,8 +118,9 @@ Prompts remain separate from skills. When the client supports MCP prompt APIs, u
|
|||||||
|
|
||||||
1. Use `MCP: List Servers` to confirm the server is enabled.
|
1. Use `MCP: List Servers` to confirm the server is enabled.
|
||||||
2. Use `MCP: Browse Resources` to confirm native skill resources exist.
|
2. Use `MCP: Browse Resources` to confirm native skill resources exist.
|
||||||
3. Restart the MCP server after changing skill files because production uses `reload=False`.
|
3. Confirm `list_resources` and `read_resource` appear in the chat tool picker when autonomous retrieval is required.
|
||||||
4. Reload the VS Code window if the server is healthy but the resource picker remains stale.
|
4. Restart the MCP server after changing skill files because production uses `reload=False`.
|
||||||
|
5. Reload the VS Code window if the server is healthy but the resource or tool picker remains stale.
|
||||||
|
|
||||||
## Further Reading
|
## Further Reading
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ uv sync
|
|||||||
Run the app locally with the static docs rebuilt first, using [Uvicorn factory mode](https://www.uvicorn.org/settings/#application):
|
Run the app locally with the static docs rebuilt first, using [Uvicorn factory mode](https://www.uvicorn.org/settings/#application):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
uv run zensical build && uv run uvicorn personal_mcp.main:create_app --factory --host 127.0.0.1 --port 8765
|
uv run zensical build && uv run uvicorn personal_mcp.web.app:create_app --factory --host 127.0.0.1 --port 8765
|
||||||
```
|
```
|
||||||
|
|
||||||
Build and run the Docker image with the same exposed port:
|
Build and run the Docker image with the same exposed port:
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ Use this page for MCP client setup, operational tools, and integration reference
|
|||||||
!!! info "VS Code MCP docs"
|
!!! info "VS Code MCP docs"
|
||||||
- [VS Code MCP servers overview](https://code.visualstudio.com/docs/agent-customization/mcp-servers)
|
- [VS Code MCP servers overview](https://code.visualstudio.com/docs/agent-customization/mcp-servers)
|
||||||
- [VS Code MCP configuration reference](https://code.visualstudio.com/docs/agents/reference/mcp-configuration)
|
- [VS Code MCP configuration reference](https://code.visualstudio.com/docs/agents/reference/mcp-configuration)
|
||||||
|
- [VS Code MCP developer guide](https://code.visualstudio.com/docs/agents/guides/mcp-developer-guide)
|
||||||
|
- [VS Code MCP Apps support](https://code.visualstudio.com/blogs/2026/01/26/mcp-apps-support)
|
||||||
- [VS Code Copilot customization overview](https://code.visualstudio.com/docs/copilot/customization/overview)
|
- [VS Code Copilot customization overview](https://code.visualstudio.com/docs/copilot/customization/overview)
|
||||||
|
|
||||||
## Debugging and Inspection
|
## Debugging and Inspection
|
||||||
|
|||||||
@@ -13,6 +13,13 @@ Use this page for implementation-oriented links across MCP SDKs and FastMCP.
|
|||||||
|
|
||||||
!!! info "FastMCP sources"
|
!!! info "FastMCP sources"
|
||||||
- [FastMCP project documentation](https://gofastmcp.com/)
|
- [FastMCP project documentation](https://gofastmcp.com/)
|
||||||
|
- [FastMCP server identity and behavior](https://gofastmcp.com/servers/server)
|
||||||
|
- [FastMCP tools and annotations](https://gofastmcp.com/servers/tools)
|
||||||
|
- [FastMCP resources and templates](https://gofastmcp.com/servers/resources)
|
||||||
|
- [FastMCP prompts](https://gofastmcp.com/servers/prompts)
|
||||||
|
- [FastMCP argument completion](https://gofastmcp.com/servers/completions)
|
||||||
|
- [FastMCP component icons](https://gofastmcp.com/servers/icons)
|
||||||
|
- [FastMCP Apps](https://gofastmcp.com/apps/overview)
|
||||||
- [FastMCP GitHub repository](https://github.com/jlowin/fastmcp)
|
- [FastMCP GitHub repository](https://github.com/jlowin/fastmcp)
|
||||||
- [FastMCP examples directory](https://github.com/jlowin/fastmcp/tree/main/examples)
|
- [FastMCP examples directory](https://github.com/jlowin/fastmcp/tree/main/examples)
|
||||||
- [FastMCP PyPI package](https://pypi.org/project/fastmcp/)
|
- [FastMCP PyPI package](https://pypi.org/project/fastmcp/)
|
||||||
|
|||||||
@@ -53,14 +53,15 @@ These utilities operate directly on the native `skill://` contract and require n
|
|||||||
In VS Code, skills can arrive through:
|
In VS Code, skills can arrive through:
|
||||||
|
|
||||||
1. explicit attachment from `Add Context > MCP Resources` or `MCP: Browse Resources`
|
1. explicit attachment from `Add Context > MCP Resources` or `MCP: Browse Resources`
|
||||||
2. a slash-command prompt that names a specific native skill URI
|
2. the generic `list_resources` and `read_resource` tools for autonomous agents
|
||||||
|
3. a slash-command prompt that names a specific native skill URI
|
||||||
|
|
||||||
Instructions can steer retrieval, but they do not guarantee automatic resource attachment in every chat surface.
|
Instructions can steer retrieval, but they do not guarantee automatic resource attachment in every chat surface. When the deferred-tool catalog omits direct MCP resource operations, use the generic tools; they delegate to the native providers and do not duplicate skill metadata or content.
|
||||||
|
|
||||||
A reliable prompt is:
|
A reliable prompt is:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
Browse personal-mcp resources and select the best matching skill://.../SKILL.md resource. Read one selected skill, inspect its _manifest only if supporting detail is needed, and reconcile the guidance with this workspace.
|
Call list_resources and select the best matching skill://.../SKILL.md resource. Use read_resource for one selected skill, inspect its _manifest only if supporting detail is needed, and reconcile the guidance with this workspace.
|
||||||
```
|
```
|
||||||
|
|
||||||
## Thin Shim Pattern
|
## Thin Shim Pattern
|
||||||
|
|||||||
+63
-2
@@ -1,24 +1,53 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from fastmcp import FastMCP
|
from fastmcp import FastMCP
|
||||||
|
from mcp.types import CompletionArgument
|
||||||
|
from mcp.types import CompletionContext
|
||||||
|
from mcp.types import Icon
|
||||||
|
from mcp.types import PromptReference
|
||||||
|
|
||||||
from personal_mcp.prompts import create_prompts_provider
|
from personal_mcp.prompts import create_prompts_provider
|
||||||
|
from personal_mcp.prompts.models import MarkdownPrompt
|
||||||
|
from personal_mcp.prompts.provider import MarkdownPromptsProvider
|
||||||
from personal_mcp.registry.load import get_docs_registry
|
from personal_mcp.registry.load import get_docs_registry
|
||||||
from personal_mcp.registry.load import read_docs_markdown_path
|
from personal_mcp.registry.load import read_docs_markdown_path
|
||||||
from personal_mcp.registry.models import DocsRegistry
|
from personal_mcp.registry.models import DocsRegistry
|
||||||
from personal_mcp.skills import create_skills_provider
|
from personal_mcp.skills import create_skills_provider
|
||||||
|
|
||||||
|
_SERVER_INSTRUCTIONS = """Personal development guidance exposed as native MCP resources and prompts.
|
||||||
|
|
||||||
|
Use prompts for parameterized workflows. For task-specific guidance, list resources, select one
|
||||||
|
skill://<name>/SKILL.md by description, and read its manifest only when supporting detail is needed.
|
||||||
|
Read-only compatibility tools expose the same resource catalog to clients without native resource access.
|
||||||
|
"""
|
||||||
|
_SERVER_ICON = Icon(
|
||||||
|
src=(
|
||||||
|
"data:image/svg+xml;base64,"
|
||||||
|
"PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NCA2NCI+"
|
||||||
|
"PHJlY3Qgd2lkdGg9IjY0IiBoZWlnaHQ9IjY0IiByeD0iOCIgZmlsbD0iIzE2N0Q4RCIvPjxwYXRoIGQ9"
|
||||||
|
"Ik0xOCAxNmgyMGw4IDh2MjRIMTh6IiBmaWxsPSJub25lIiBzdHJva2U9IndoaXRlIiBzdHJva2Utd2lk"
|
||||||
|
"dGg9IjQiLz48cGF0aCBkPSJNMzggMTZ2MTBoOE0yNSAzM2gxNE0yNSA0MGgxNCIgZmlsbD0ibm9uZSIg"
|
||||||
|
"c3Ryb2tlPSJ3aGl0ZSIgc3Ryb2tlLXdpZHRoPSI0Ii8+PC9zdmc+"
|
||||||
|
),
|
||||||
|
mime_type="image/svg+xml",
|
||||||
|
sizes=["64x64"],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def _ro_annotations() -> dict[str, bool]:
|
def _ro_annotations() -> dict[str, bool]:
|
||||||
return {
|
return {
|
||||||
"readOnlyHint": True,
|
"readOnlyHint": True,
|
||||||
"idempotentHint": True,
|
"idempotentHint": True,
|
||||||
|
"openWorldHint": False,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def _register_components(mcp: FastMCP, registry: DocsRegistry) -> None:
|
def _register_components(mcp: FastMCP, registry: DocsRegistry) -> None:
|
||||||
@mcp.resource(
|
@mcp.resource(
|
||||||
"resource://docs/{path*}",
|
"resource://docs/{path*}",
|
||||||
|
name="docs_markdown",
|
||||||
|
title="Documentation Markdown",
|
||||||
|
description="Read a packaged documentation page by its path relative to the docs root.",
|
||||||
mime_type="text/markdown",
|
mime_type="text/markdown",
|
||||||
tags={"docs"},
|
tags={"docs"},
|
||||||
annotations=_ro_annotations(),
|
annotations=_ro_annotations(),
|
||||||
@@ -30,6 +59,7 @@ def _register_components(mcp: FastMCP, registry: DocsRegistry) -> None:
|
|||||||
def _register_resource_tools(mcp: FastMCP) -> None:
|
def _register_resource_tools(mcp: FastMCP) -> None:
|
||||||
@mcp.tool(
|
@mcp.tool(
|
||||||
name="list_resources",
|
name="list_resources",
|
||||||
|
title="List Resources",
|
||||||
description=(
|
description=(
|
||||||
"List available MCP resources and URI templates. Use before read_resource to discover skill guidance."
|
"List available MCP resources and URI templates. Use before read_resource to discover skill guidance."
|
||||||
),
|
),
|
||||||
@@ -61,6 +91,7 @@ def _register_resource_tools(mcp: FastMCP) -> None:
|
|||||||
|
|
||||||
@mcp.tool(
|
@mcp.tool(
|
||||||
name="read_resource",
|
name="read_resource",
|
||||||
|
title="Read Resource",
|
||||||
description="Read a resource URI returned by list_resources, including skill files, manifests, and references.",
|
description="Read a resource URI returned by list_resources, including skill files, manifests, and references.",
|
||||||
annotations=_ro_annotations(),
|
annotations=_ro_annotations(),
|
||||||
)
|
)
|
||||||
@@ -69,11 +100,41 @@ def _register_resource_tools(mcp: FastMCP) -> None:
|
|||||||
return result.model_dump(mode="json", exclude_none=True)
|
return result.model_dump(mode="json", exclude_none=True)
|
||||||
|
|
||||||
|
|
||||||
|
def _register_prompt_completions(mcp: FastMCP, provider: MarkdownPromptsProvider) -> None:
|
||||||
|
@mcp.completion
|
||||||
|
async def complete_prompt_argument(
|
||||||
|
ref: object,
|
||||||
|
argument: CompletionArgument,
|
||||||
|
context: CompletionContext | None,
|
||||||
|
) -> list[str] | None:
|
||||||
|
del context
|
||||||
|
if not isinstance(ref, PromptReference):
|
||||||
|
return None
|
||||||
|
|
||||||
|
prompt = await provider.get_prompt(ref.name)
|
||||||
|
if not isinstance(prompt, MarkdownPrompt):
|
||||||
|
return None
|
||||||
|
|
||||||
|
definition = prompt.definitions.get(argument.name)
|
||||||
|
if definition is None or definition.choices is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
prefix = argument.value.casefold()
|
||||||
|
return [choice for choice in definition.choices if choice.casefold().startswith(prefix)]
|
||||||
|
|
||||||
|
|
||||||
def create_mcp() -> FastMCP:
|
def create_mcp() -> FastMCP:
|
||||||
registry = get_docs_registry()
|
registry = get_docs_registry()
|
||||||
mcp = FastMCP("personal-mcp", on_duplicate="error")
|
mcp = FastMCP(
|
||||||
|
"personal-mcp",
|
||||||
|
instructions=_SERVER_INSTRUCTIONS,
|
||||||
|
icons=[_SERVER_ICON],
|
||||||
|
on_duplicate="error",
|
||||||
|
)
|
||||||
_register_components(mcp, registry)
|
_register_components(mcp, registry)
|
||||||
mcp.add_provider(create_prompts_provider())
|
prompts_provider = create_prompts_provider()
|
||||||
|
mcp.add_provider(prompts_provider)
|
||||||
mcp.add_provider(create_skills_provider())
|
mcp.add_provider(create_skills_provider())
|
||||||
_register_resource_tools(mcp)
|
_register_resource_tools(mcp)
|
||||||
|
_register_prompt_completions(mcp, prompts_provider)
|
||||||
return mcp
|
return mcp
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ class MarkdownPrompt(Prompt):
|
|||||||
metadata = definition.metadata
|
metadata = definition.metadata
|
||||||
return cls(
|
return cls(
|
||||||
name=definition.prompt_id,
|
name=definition.prompt_id,
|
||||||
|
title=definition.prompt_id.replace("-", " ").title(),
|
||||||
version=metadata.version,
|
version=metadata.version,
|
||||||
description=metadata.description,
|
description=metadata.description,
|
||||||
tags=set(metadata.tags),
|
tags=set(metadata.tags),
|
||||||
|
|||||||
Reference in New Issue
Block a user