1 Commits
Author SHA1 Message Date
John Lancaster 55ef7e972a debug launch config 2026-08-29 20:45:15 -05:00
8 changed files with 90 additions and 48 deletions
+18
View File
@@ -0,0 +1,18 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "Python: personal-mcp entrypoint",
"type": "debugpy",
"request": "launch",
"module": "personal_mcp.__main__",
"cwd": "${workspaceFolder}",
"console": "integratedTerminal",
"justMyCode": true,
"env": {
"PYTHONUNBUFFERED": "1"
},
"args": [ "--port", "8766", "--reload" ]
}
]
}
+1 -7
View File
@@ -51,13 +51,7 @@
"command": "uv", "command": "uv",
"args": [ "args": [
"run", "run",
"uvicorn", "personal-mcp",
"personal_mcp.main:create_app",
"--factory",
"--host",
"127.0.0.1",
"--port",
"8000",
"--reload" "--reload"
], ],
"options": { "options": {
+25 -30
View File
@@ -1,57 +1,52 @@
FROM python:3.14-slim AS builder FROM python:3.14-slim AS builder
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
ENV PYTHONDONTWRITEBYTECODE=1 \ ENV PYTHONUNBUFFERED=1 \
PYTHONUNBUFFERED=1 \ UV_SYSTEM_CERTS=1 \
UV_PYTHON_DOWNLOADS=0 \
UV_NO_MANAGED_PYTHON=1 \
UV_SYSTEM_PYTHON=1 \
UV_PROJECT_ENVIRONMENT=/usr/local \
UV_COMPILE_BYTECODE=1 \ UV_COMPILE_BYTECODE=1 \
UV_LINK_MODE=copy \ UV_NO_DEV=1 \
UV_LOCKED=1 UV_LOCKED=1 \
UV_LINK_MODE=copy
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
WORKDIR /app WORKDIR /app
RUN --mount=type=cache,target=/root/.cache/uv \ RUN --mount=type=cache,target=/root/.cache/uv \
--mount=type=bind,source=zensical.toml,target=zensical.toml \ --mount=type=bind,source=zensical.toml,target=zensical.toml \
--mount=type=bind,source=docs/,target=docs/ \ --mount=type=bind,source=src/personal_mcp/docs/,target=src/personal_mcp/docs/ \
uvx zensical build uvx zensical build --clean --strict
RUN --mount=type=cache,target=/root/.cache/uv \ RUN --mount=type=cache,target=/root/.cache/uv \
--mount=type=bind,source=uv.lock,target=uv.lock \ --mount=type=bind,source=uv.lock,target=uv.lock \
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \ --mount=type=bind,source=pyproject.toml,target=pyproject.toml \
uv sync --no-install-project uv sync --no-install-project
# COPY --chown=appuser:appuser . /app COPY pyproject.toml uv.lock README.md /app/
COPY ./src /app/src
# RUN --mount=type=cache,target=/root/.cache/uv \ RUN --mount=type=cache,target=/root/.cache/uv \
# uv sync --no-editable uv sync
FROM python:3.14-slim AS runtime FROM python:3.14-slim AS runtime
ENV PYTHONDONTWRITEBYTECODE=1 \ ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1 \ PYTHONUNBUFFERED=1
PATH="/app/.venv/bin:$PATH" \
PERSONAL_MCP_HOST=0.0.0.0 \
PERSONAL_MCP_PORT=8765 \
PERSONAL_MCP_RELOAD=false \
PERSONAL_MCP_SITE_DIR=/app/site
WORKDIR /app
EXPOSE 8765
RUN groupadd --system --gid 1001 appuser && \ RUN groupadd --system --gid 1001 appuser && \
useradd --system --uid 1001 --gid appuser appuser useradd --system --uid 1001 --gid appuser appuser
COPY --from=ghcr.io/astral-sh/uv:latest --chown=appuser:appuser /uv /uvx /bin/ WORKDIR /app
COPY --from=builder --chown=appuser:appuser /app/.venv /app/.venv
COPY --from=builder --chown=appuser:appuser /app/site /app/site
COPY --chown=appuser:appuser ./docs /app/docs
RUN --mount=type=cache,target=/root/.cache/uv \ RUN chown appuser:appuser /app
--mount=type=bind,source=uv.lock,target=uv.lock \
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \ COPY --from=builder --chown=appuser:appuser /usr/local/lib /usr/local/lib
--mount=type=bind,source=src/,target=src/ \ COPY --from=builder --chown=appuser:appuser /usr/local/bin /usr/local/bin
uv sync --no-editable --refresh-package prompts COPY --from=builder --chown=appuser:appuser /app /app
USER appuser USER appuser
ENTRYPOINT ["python", "-m", "personal_mcp"] ENTRYPOINT ["/usr/local/bin/personal-mcp"]
+16
View File
@@ -0,0 +1,16 @@
# JSL MCP
```shell
uv run mcp-stdio
```
```shell
uv run fastmcp list --command "uv run mcp-stdio" --prompts
```
```shell
uv run fastmcp call --command "uv run mcp-stdio" \
--target authoring --prompt \
--input-json '{"artifact_type":"prompt","artifact_id":"release-notes","goal":"Create a reusable release-notes workflow."}' \
--json
```
+9 -4
View File
@@ -1,8 +1,13 @@
services: services:
personal-mcp: app:
build: image: personal-mcp:latest
context: . build: .
dockerfile: Dockerfile
restart: unless-stopped restart: unless-stopped
ports: ports:
- "8765:8765" - "8765:8765"
environment:
PERSONAL_MCP_PORT: 8765
PERSONAL_MCP_HOST: 0.0.0.0
PERSONAL_MCP_RELOAD: 1
volumes:
- ./src:/app/src:ro
+5 -6
View File
@@ -1,5 +1,5 @@
[project] [project]
name = "prompts" name = "personal_mcp"
version = "2.0.0" version = "2.0.0"
requires-python = ">=3.12" requires-python = ">=3.12"
dependencies = [ dependencies = [
@@ -17,13 +17,11 @@ constraint-dependencies = ["fastmcp-slim==4.0.0b4"]
[project.scripts] [project.scripts]
personal-mcp = "personal_mcp.__main__:main" personal-mcp = "personal_mcp.__main__:main"
mcp-stdio = "personal_mcp.mcp:run_stdio"
[build-system] [build-system]
requires = ["hatchling"] requires = ["uv_build>=0.12.7,<0.13"]
build-backend = "hatchling.build" build-backend = "uv_build"
[tool.hatch.build.targets.wheel]
packages = ["src/personal_mcp"]
[dependency-groups] [dependency-groups]
dev = [ dev = [
@@ -52,3 +50,4 @@ markers = [
[tool.ty.src] [tool.ty.src]
include = ["src", "tests"] include = ["src", "tests"]
exclude = ["src/personal_mcp/docs/skills/*/examples/*.py"]
+1 -1
View File
@@ -7,7 +7,7 @@ def main(cli: bool = True) -> None:
"""Run the root MCP server.""" """Run the root MCP server."""
settings = get_settings(cli=cli) settings = get_settings(cli=cli)
uvicorn.run( uvicorn.run(
"personal_mcp.web.app:create_app", "personal_mcp.app:create_app",
factory=True, factory=True,
host=settings.host, host=settings.host,
port=settings.port, port=settings.port,
+15
View File
@@ -16,6 +16,7 @@ from .mcp import create_mcp
def create_app(settings: Settings | None = None) -> FastAPI: def create_app(settings: Settings | None = None) -> FastAPI:
runtime_settings = settings if settings is not None else get_settings() runtime_settings = settings if settings is not None else get_settings()
docs_route = runtime_settings.mounts.docs.rstrip("/") or "/docs"
mcp_app = create_mcp().http_app( mcp_app = create_mcp().http_app(
json_response=True, json_response=True,
stateless_http=True, stateless_http=True,
@@ -29,6 +30,20 @@ def create_app(settings: Settings | None = None) -> FastAPI:
lifespan=app_lifespan, lifespan=app_lifespan,
) )
app.state.settings = runtime_settings app.state.settings = runtime_settings
async def redirect_root_to_docs() -> RedirectResponse:
return RedirectResponse(
url=docs_route,
status_code=status.HTTP_307_TEMPORARY_REDIRECT,
)
app.add_api_route(
"/",
redirect_root_to_docs,
methods=["GET", "HEAD"],
include_in_schema=False,
)
app.mount(runtime_settings.mounts.mcp, mcp_app, name="mcp") app.mount(runtime_settings.mounts.mcp, mcp_app, name="mcp")
return app return app