From 75b0c8d19207a75fae644f002b2e2476ed347123 Mon Sep 17 00:00:00 2001 From: John Lancaster <32917998+jsl12@users.noreply.github.com> Date: Fri, 19 Jun 2026 16:56:45 -0500 Subject: [PATCH] vscode skill --- docs/skills/vscode-configuration/SKILL.md | 95 ++++++++++++++++ .../references/debug-launch-configurations.md | 101 ++++++++++++++++++ .../references/fastapi-debugpy-launch.md | 98 +++++++++++++++++ .../references/tasks-json-configuration.md | 92 ++++++++++++++++ src/personal_mcp/mcp.py | 6 +- .../skills/vscode_configuration/__init__.py | 1 + .../skills/vscode_configuration/metadata.yaml | 15 +++ .../skills/vscode_configuration/server.py | 20 ++++ zensical.toml | 7 ++ 9 files changed, 434 insertions(+), 1 deletion(-) create mode 100644 docs/skills/vscode-configuration/SKILL.md create mode 100644 docs/skills/vscode-configuration/references/debug-launch-configurations.md create mode 100644 docs/skills/vscode-configuration/references/fastapi-debugpy-launch.md create mode 100644 docs/skills/vscode-configuration/references/tasks-json-configuration.md create mode 100644 src/personal_mcp/skills/vscode_configuration/__init__.py create mode 100644 src/personal_mcp/skills/vscode_configuration/metadata.yaml create mode 100644 src/personal_mcp/skills/vscode_configuration/server.py diff --git a/docs/skills/vscode-configuration/SKILL.md b/docs/skills/vscode-configuration/SKILL.md new file mode 100644 index 0000000..710c254 --- /dev/null +++ b/docs/skills/vscode-configuration/SKILL.md @@ -0,0 +1,95 @@ +--- +name: vscode-configuration +description: 'Create and troubleshoot VS Code workspace configuration for Python projects, with focused patterns for launch.json debugpy/FastAPI debugging and tasks.json task automation.' +argument-hint: 'What do you need: debug setup, FastAPI debug run profile, tasks.json automation, or all of them?' +--- + +# VS Code Configuration + +Use this skill to design or repair repeatable VS Code workspace configuration for local development workflows. + +## When to Use + +- You need to create or fix `.vscode/launch.json` debug profiles. +- You need robust Python debugging with `debugpy`. +- You need FastAPI-specific launch profiles (app module, host/port, reload options, env files). +- You need `.vscode/tasks.json` build/test/run tasks and optional debug pre-launch integration. +- You need consistent workspace onboarding where users can run and debug from VS Code with minimal manual setup. + +## Progressive References + +Load only the page that matches the current request: + +- Launch profile mechanics and debugpy patterns: [debug launch configurations](./references/debug-launch-configurations.md) +- FastAPI-focused debug profiles using debugpy: [FastAPI + debugpy launch patterns](./references/fastapi-debugpy-launch.md) +- Task runner setup in VS Code: [tasks.json project tasks](./references/tasks-json-configuration.md) + +## Procedure + +### Step 1: Capture the Runtime Shape + +Collect the minimum context before writing files: + +1. Python entry shape: module path vs script path. +2. Framework runtime: plain script, FastAPI with uvicorn, or mixed services. +3. Required environment: env file, env vars, cwd, and PYTHONPATH needs. +4. Task expectations: run app, run tests, lint/format, one-off setup. + +Completion check: you can state exactly what command should run for debug and for task execution. + +### Step 2: Create launch.json Profiles + +1. Add at least one stable baseline profile before specialized variants. +2. Prefer module-based launches where packaging/import paths matter. +3. Keep debugger options explicit (`justMyCode`, `console`, `cwd`, `envFile`). +4. Add purpose-built profiles instead of one overloaded profile. + +For concrete patterns, open [debug launch configurations](./references/debug-launch-configurations.md). + +Completion check: selecting each profile starts the intended process without manual edits. + +### Step 3: Add FastAPI Profiles When Needed + +1. Use a dedicated FastAPI profile that launches `uvicorn` via module mode. +2. Keep host/port/reload/log-level as explicit args. +3. Include `jinja` debugging only if templates are in scope. +4. Add an attach profile when launching via external `debugpy` listener. + +For complete examples, open [FastAPI + debugpy launch patterns](./references/fastapi-debugpy-launch.md). + +Completion check: breakpoints hit in app code and startup path, and profile behavior matches dev vs non-dev expectations. + +### Step 4: Add tasks.json for Repeated Commands + +1. Create named tasks for run, test, lint, and docs/build steps as needed. +2. For Python projects, keep commands consistent with the repo package manager. +3. Use `problemMatcher` where parsers exist and background flags for long-running tasks. +4. Link debug profiles to tasks with `preLaunchTask` only when startup sequencing is required. + +For task schema and examples, open [tasks.json project tasks](./references/tasks-json-configuration.md). + +Completion check: tasks run from Command Palette and can be reused by debug profiles. + +### Step 5: Validate End-to-End + +1. Run each launch profile once. +2. Run each task once. +3. Verify paths, env files, and interpreter assumptions on a clean workspace reload. +4. Record any project-specific defaults in comments or docs if non-obvious. + +Completion check: a teammate can clone the repo, open VS Code, and run/debug with only documented prerequisites. + +## Decision Points + +- If the app is imported as a package, prefer module launches over direct script paths. +- If runtime is started outside VS Code, add attach profile instead of forcing launch mode. +- If there are long-running dev servers, pair with background tasks. +- If test command differs by repo convention, mirror that command in tasks exactly. + +## Output Contract + +Return: + +1. Created or updated VS Code config files and profile/task names. +2. Any assumptions (module path, env file, command runner). +3. Validation results and any unresolved decisions. diff --git a/docs/skills/vscode-configuration/references/debug-launch-configurations.md b/docs/skills/vscode-configuration/references/debug-launch-configurations.md new file mode 100644 index 0000000..f702dc4 --- /dev/null +++ b/docs/skills/vscode-configuration/references/debug-launch-configurations.md @@ -0,0 +1,101 @@ +# Debug Launch Configurations in VS Code + +This reference focuses on Python debugging through `debugpy` using `.vscode/launch.json`. + +## Core Structure + +A minimal launch file: + +```json +{ + "version": "0.2.0", + "configurations": [] +} +``` + +Useful fields for Python configs: + +- `type`: Use `debugpy`. +- `request`: Usually `launch`, sometimes `attach`. +- `name`: Friendly profile name shown in the Run and Debug panel. +- `program`: Script path for script-based entry. +- `module`: Module name for `python -m ...` style launches. +- `args`: CLI arguments. +- `cwd`: Working directory. +- `env` / `envFile`: Environment variables. +- `console`: `integratedTerminal` is usually most practical. +- `justMyCode`: `true` by default; set `false` when stepping into dependencies. + +## Launch vs Attach + +Use `launch` when VS Code should start the process. +Use `attach` when the process already runs with debugpy listening. + +Attach profile example: + +```json +{ + "name": "Python: Attach (debugpy :5678)", + "type": "debugpy", + "request": "attach", + "connect": { + "host": "127.0.0.1", + "port": 5678 + }, + "justMyCode": true +} +``` + +Remote process side command example: + +```bash +python -m debugpy --listen 5678 -m your_package.main +``` + +## Script and Module Patterns + +Script pattern: + +```json +{ + "name": "Python: Script", + "type": "debugpy", + "request": "launch", + "program": "${workspaceFolder}/src/app.py", + "cwd": "${workspaceFolder}", + "console": "integratedTerminal", + "justMyCode": true +} +``` + +Module pattern: + +```json +{ + "name": "Python: Module", + "type": "debugpy", + "request": "launch", + "module": "your_package.main", + "cwd": "${workspaceFolder}", + "console": "integratedTerminal", + "justMyCode": true +} +``` + +Prefer module mode when imports depend on package layout. + +## Environment and Interpreter Notes + +- Use `envFile` for shared local variables, commonly `${workspaceFolder}/.env`. +- Keep secrets out of committed launch configs. +- Ensure the selected VS Code interpreter matches project tooling. + +## Troubleshooting + +If breakpoints do not hit: + +1. Confirm the right profile is selected. +2. Confirm the file path/module path is correct. +3. Disable `justMyCode` temporarily to inspect call flow. +4. Confirm no stale background process is occupying the expected port. +5. Confirm workspace root and `cwd` align with imports. diff --git a/docs/skills/vscode-configuration/references/fastapi-debugpy-launch.md b/docs/skills/vscode-configuration/references/fastapi-debugpy-launch.md new file mode 100644 index 0000000..1d53785 --- /dev/null +++ b/docs/skills/vscode-configuration/references/fastapi-debugpy-launch.md @@ -0,0 +1,98 @@ +# FastAPI Debug Launch with debugpy + +This reference provides practical `.vscode/launch.json` patterns for FastAPI applications started with uvicorn. + +## Launch FastAPI via Module + +Preferred profile: + +```json +{ + "name": "FastAPI: Uvicorn (debug)", + "type": "debugpy", + "request": "launch", + "module": "uvicorn", + "args": [ + "your_package.main:app", + "--host", + "127.0.0.1", + "--port", + "8000", + "--reload", + "--log-level", + "debug" + ], + "cwd": "${workspaceFolder}", + "envFile": "${workspaceFolder}/.env", + "console": "integratedTerminal", + "justMyCode": true, + "jinja": true +} +``` + +Why module mode: it matches `python -m uvicorn ...` behavior and avoids path ambiguity. + +## Launch with Factory Pattern + +If app is created via factory function: + +```json +{ + "name": "FastAPI: Uvicorn factory (debug)", + "type": "debugpy", + "request": "launch", + "module": "uvicorn", + "args": [ + "your_package.main:create_app", + "--factory", + "--host", + "127.0.0.1", + "--port", + "8000", + "--reload" + ], + "cwd": "${workspaceFolder}", + "console": "integratedTerminal", + "justMyCode": true +} +``` + +## Attach to an Existing FastAPI Process + +If the app is launched externally, start with debugpy: + +```bash +python -m debugpy --listen 5678 -m uvicorn your_package.main:app --host 127.0.0.1 --port 8000 --reload +``` + +Attach profile: + +```json +{ + "name": "FastAPI: Attach (5678)", + "type": "debugpy", + "request": "attach", + "connect": { + "host": "127.0.0.1", + "port": 5678 + }, + "justMyCode": true +} +``` + +## Common FastAPI Debug Pitfalls + +1. Wrong import target in `your_package.main:app` or factory symbol. +2. `cwd` does not match source layout. +3. Auto-reload creating confusion about active process when breakpoints are set in startup code. +4. Port collisions from old uvicorn processes. +5. Environment variables not loaded because `envFile` path is wrong. + +## Practical Quality Gate + +A profile is considered valid when: + +1. Server starts from VS Code Run and Debug. +2. A breakpoint inside an endpoint is hit on request. +3. A breakpoint in startup/lifespan logic is hit at app boot. +4. Terminal output appears in integrated terminal with expected log level. diff --git a/docs/skills/vscode-configuration/references/tasks-json-configuration.md b/docs/skills/vscode-configuration/references/tasks-json-configuration.md new file mode 100644 index 0000000..2d51bcb --- /dev/null +++ b/docs/skills/vscode-configuration/references/tasks-json-configuration.md @@ -0,0 +1,92 @@ +# Configure Project Tasks in tasks.json + +Use `.vscode/tasks.json` to define repeatable project commands and optional hooks for debugging. + +## Minimal File + +```json +{ + "version": "2.0.0", + "tasks": [] +} +``` + +## Task Fields You Will Use Most + +- `label`: Task name shown in VS Code. +- `type`: Usually `shell`. +- `command`: Executable to run. +- `args`: Command arguments. +- `options.cwd`: Working directory. +- `group`: Mark default build or test tasks. +- `problemMatcher`: Parse errors into the Problems panel. +- `isBackground`: `true` for long-running tasks (for example dev server watch). + +## Python Project Example + +```json +{ + "version": "2.0.0", + "tasks": [ + { + "label": "App: Run", + "type": "shell", + "command": "uv", + "args": ["run", "uvicorn", "personal_mcp.main:app", "--host", "127.0.0.1", "--port", "8000", "--reload"], + "options": { + "cwd": "${workspaceFolder}" + }, + "isBackground": true, + "problemMatcher": [] + }, + { + "label": "Tests: Pytest", + "type": "shell", + "command": "uv", + "args": ["run", "pytest"], + "options": { + "cwd": "${workspaceFolder}" + }, + "group": "test", + "problemMatcher": [] + } + ] +} +``` + +## Connect Tasks to Debug Profiles + +In `launch.json`, you can run a task first: + +```json +{ + "name": "FastAPI: Attach", + "type": "debugpy", + "request": "attach", + "connect": { + "host": "127.0.0.1", + "port": 5678 + }, + "preLaunchTask": "App: Run" +} +``` + +Use this only when startup sequencing is needed. + +## Task Design Guidelines + +1. Keep labels stable and descriptive. +2. Prefer one task per intent instead of monolithic shell commands. +3. Keep shell portability in mind if teammates use multiple OSes. +4. Avoid embedding secrets directly in task definitions. +5. Mark long-running tasks with `isBackground` and keep matchers explicit. + +## Troubleshooting + +If a task fails unexpectedly: + +1. Run the underlying command directly in terminal. +2. Confirm `options.cwd` points to expected workspace root. +3. Confirm tool availability in environment path. +4. Confirm quoting and argument boundaries in `args`. +5. Confirm the task is not blocked by an outdated background process. diff --git a/src/personal_mcp/mcp.py b/src/personal_mcp/mcp.py index cde29f9..84018f3 100644 --- a/src/personal_mcp/mcp.py +++ b/src/personal_mcp/mcp.py @@ -1,7 +1,9 @@ from fastmcp import FastMCP from personal_mcp.catalog.server import catalog_server -from personal_mcp.skills.copilot_customization.server import copilot_customization_server +from personal_mcp.skills.copilot_customization.server import ( + copilot_customization_server, +) from personal_mcp.skills.fastapi_async_sqlalchemy_modernization.server import ( fastapi_async_sqlalchemy_modernization_server, ) @@ -15,6 +17,7 @@ from personal_mcp.skills.pytest_scaffolding.server import pytest_scaffolding_ser from personal_mcp.skills.python_logging_dictconfig.server import ( python_logging_dictconfig_server, ) +from personal_mcp.skills.vscode_configuration.server import vscode_configuration_server from personal_mcp.skills.zensical_docs.server import zensical_docs_server mcp = FastMCP("personal-mcp") @@ -30,5 +33,6 @@ mcp.mount(nicegui_server, namespace="nicegui") mcp.mount(nicegui_ui_customization_server, namespace="nicegui_ui_customization") mcp.mount(pytest_scaffolding_server, namespace="pytest_scaffolding") mcp.mount(python_logging_dictconfig_server, namespace="python_logging_dictconfig") +mcp.mount(vscode_configuration_server, namespace="vscode_configuration") mcp.mount(fastapi_uv_docker_server, namespace="fastapi_uv_docker") mcp.mount(zensical_docs_server, namespace="zensical_docs") diff --git a/src/personal_mcp/skills/vscode_configuration/__init__.py b/src/personal_mcp/skills/vscode_configuration/__init__.py new file mode 100644 index 0000000..ba2fbbd --- /dev/null +++ b/src/personal_mcp/skills/vscode_configuration/__init__.py @@ -0,0 +1 @@ +"""VS Code configuration skill package.""" diff --git a/src/personal_mcp/skills/vscode_configuration/metadata.yaml b/src/personal_mcp/skills/vscode_configuration/metadata.yaml new file mode 100644 index 0000000..7a74b44 --- /dev/null +++ b/src/personal_mcp/skills/vscode_configuration/metadata.yaml @@ -0,0 +1,15 @@ +id: vscode-configuration +name: VS Code Configuration +version: 1.0.0 +description: Create and troubleshoot VS Code launch and task configuration for Python and FastAPI projects. +tags: + - vscode + - launch-json + - tasks-json + - debugpy + - fastapi + - python + - skills +capabilities: + - resource://skills/vscode-configuration/document +depends_on: [] diff --git a/src/personal_mcp/skills/vscode_configuration/server.py b/src/personal_mcp/skills/vscode_configuration/server.py new file mode 100644 index 0000000..59a29e0 --- /dev/null +++ b/src/personal_mcp/skills/vscode_configuration/server.py @@ -0,0 +1,20 @@ +from pathlib import Path + +import yaml +from fastmcp import FastMCP + +from personal_mcp.skills.document_loader import load_skill_document_from_metadata + +vscode_configuration_server = FastMCP("vscode-configuration") +_METADATA_PATH = Path(__file__).with_name("metadata.yaml") +_METADATA = yaml.safe_load(_METADATA_PATH.read_text(encoding="utf-8")) or {} + + +@vscode_configuration_server.resource("resource://skills/vscode-configuration/document") +def skill_document() -> dict[str, str]: + """Return the canonical Markdown document for this skill.""" + return load_skill_document_from_metadata( + skill_id="vscode-configuration", + namespace="vscode_configuration", + metadata=_METADATA, + ) diff --git a/zensical.toml b/zensical.toml index 916362c..2fa57e7 100644 --- a/zensical.toml +++ b/zensical.toml @@ -51,6 +51,7 @@ nav = [ { "MCP" = "mcp_layout.md" }, { "Copilot" = "copilot.md" }, { "Usage" = "usage.md" }, + { "Future Work" = "future_work.md" }, { "New Skill" = "new_skill.md" }, { "Security" = "securing.md" }, ] }, @@ -59,6 +60,12 @@ nav = [ { "Overview" = "skills/copilot-customization/SKILL.md" }, { "VS Code" = "skills/copilot-customization/references/vscode-customization.md" }, ] }, + { "VS Code Config" = [ + { "Overview" = "skills/vscode-configuration/SKILL.md" }, + { "Debug Launch" = "skills/vscode-configuration/references/debug-launch-configurations.md" }, + { "FastAPI Debug" = "skills/vscode-configuration/references/fastapi-debugpy-launch.md" }, + { "Tasks" = "skills/vscode-configuration/references/tasks-json-configuration.md" }, + ] }, { "FastAPI UV" = [ { "Overview" = "skills/fastapi-uv-docker/SKILL.md" }, { "Best" = "skills/fastapi-uv-docker/references/fastapi-best-practices.md" },