feat: dotenv config files and plugin registry support#75
Merged
Conversation
Add plugin manifest, MCP server config, and session start hook that checks for OUTLINE_API_KEY configuration. Update README with plugin installation instructions. https://claude.ai/code/session_01LV2F6VAyLq2cZexnxSprkw
Add server.json for the Official MCP Registry (registry.modelcontextprotocol.io) with PyPI package metadata. This enables discovery via the GitHub MCP Registry and VS Code MCP Gallery. Add CI workflow for automated registry publishing on version tags. Add VS Code one-click install badge and mcp-name tag for PyPI validation. https://claude.ai/code/session_01LV2F6VAyLq2cZexnxSprkw
The vscode:mcp/install deep link now includes ${input:outline-api-key}
and ${input:outline-api-url} environment variables, which causes VS Code
to prompt the user for these values during installation.
https://claude.ai/code/session_01LV2F6VAyLq2cZexnxSprkw
Enables ownership claiming on Glama's MCP server directory, which also powers the awesome-mcp-servers list. https://claude.ai/code/session_01LV2F6VAyLq2cZexnxSprkw
- Update server.json from 2025-07-09 (snake_case) to 2025-09-29 (camelCase) schema to fix MCP Registry publishing - Add title, websiteUrl, isSecret fields to server.json - Create marketplace.json for Claude Code plugin marketplace support - Add mcpServers and hooks paths to plugin.json - Fix OUTLINE_DYNAMIC_TOOL_LIST docs: default is false, not true - Fix plugin install command to use plugin@marketplace format - Remove misleading CI workflow comment about PyPI dependency https://claude.ai/code/session_01LV2F6VAyLq2cZexnxSprkw
Enables publishing to Smithery.ai MCP server registry. Configures stdio transport with uvx runtime and prompts for API key and URL. https://claude.ai/code/session_01LV2F6VAyLq2cZexnxSprkw
1212668 to
e4ff803
Compare
smithery.yaml docs are 404 and the current Smithery workflow uses `smithery mcp publish` CLI instead. Will publish manually. https://claude.ai/code/session_01LV2F6VAyLq2cZexnxSprkw
Take origin/main's refactored README that moves detailed documentation into docs/ subdirectory. The Claude Code plugin section is already included in main's version. https://claude.ai/code/session_01LV2F6VAyLq2cZexnxSprkw
The plugin section existed in the README before the docs refactor but wasn't migrated to docs/client-setup.md. Adds it alongside the other client instructions and updates the README cross-reference. https://claude.ai/code/session_01LV2F6VAyLq2cZexnxSprkw
Add docs/registries.md mapping each marketplace/registry to its config files and publish mechanism. Update server.json schema from 2025-09-29 to the latest 2025-12-11 (backwards-compatible, no field changes). https://claude.ai/code/session_01LV2F6VAyLq2cZexnxSprkw
The one-click VS Code MCP install badge was lost when the README was simplified during the merge from main's docs refactor. https://claude.ai/code/session_01LV2F6VAyLq2cZexnxSprkw
The badge was using insiders.vscode.dev/redirect which targets VS Code Insiders. Switch to vscode.dev/redirect/mcp/install which correctly opens stable VS Code. https://claude.ai/code/session_01LV2F6VAyLq2cZexnxSprkw
Claude Code requires all plugin paths to start with ./ and cannot traverse outside the plugin directory. Since .mcp.json and hooks/hooks.json are already in the default auto-discovery locations, the explicit paths are unnecessary. https://claude.ai/code/session_01LV2F6VAyLq2cZexnxSprkw
Remove mention of MCP server and hook paths since those are now auto-discovered from default locations, not referenced in plugin.json. https://claude.ai/code/session_01LV2F6VAyLq2cZexnxSprkw
The ${input:...} syntax requires a matching inputs block in
.vscode/mcp.json which the one-click install URL cannot define.
Use a plain YOUR_API_KEY placeholder that the user replaces manually.
Also drop OUTLINE_API_URL since it's optional and has a default.
https://claude.ai/code/session_01LV2F6VAyLq2cZexnxSprkw
Replace static YOUR_API_KEY placeholder in VS Code install badge with promptString inputs that ask for the API key and URL during installation. Add one-click install badges for VS Code, VS Code Insiders, and Cursor. Update client-setup docs to use inputs pattern as the recommended approach. https://claude.ai/code/session_01LV2F6VAyLq2cZexnxSprkw
Keep install buttons only in the One-Click Install section to avoid redundancy. https://claude.ai/code/session_01LV2F6VAyLq2cZexnxSprkw
Adds python-dotenv to automatically load configuration from ~/.config/mcp-outline/.env at startup. Existing environment variables take priority over values in the file, so users can still override per-project via shell or .mcp.json env blocks. This reduces friction for marketplace-style installs where users just need to drop their API key in one file. https://claude.ai/code/session_01LV2F6VAyLq2cZexnxSprkw
When OUTLINE_API_KEY is missing, the hook now tells users to create ~/.config/mcp-outline/.env instead of editing shell profiles. Simpler setup path for marketplace-style installs. https://claude.ai/code/session_01LV2F6VAyLq2cZexnxSprkw
Tests 2 and 3 were calling load_dotenv() directly instead of going through the server module's import-time code. Now they patch Path.home() to redirect to a tmp dir with a real .env file, then import the server module, verifying the full integration. https://claude.ai/code/session_01LV2F6VAyLq2cZexnxSprkw
The env block in .mcp.json was setting OUTLINE_API_KEY to an empty
string via ${OUTLINE_API_KEY:-} when the shell var wasn't set. This
prevented load_dotenv(override=False) from loading the value from
~/.config/mcp-outline/.env since the key already existed (as "").
- Remove all env vars from .mcp.json — the server inherits the parent
env and loads its own config file via dotenv
- Mark OUTLINE_API_KEY as isRequired=false in server.json
- Update session hook to check the config file before warning
https://claude.ai/code/session_01LV2F6VAyLq2cZexnxSprkw
MCP clients (e.g. Claude Code) pass empty strings for unset
variables via their env block (${VAR:-} resolves to "").
These empty values prevented load_dotenv(override=False) from
loading the config file values. Now empty OUTLINE_* vars are
stripped before dotenv runs, and the .mcp.json env block is
restored so real env var values still pass through.
https://claude.ai/code/session_01LV2F6VAyLq2cZexnxSprkw
SessionStart hooks fire once per session and should use an empty string matcher, not "startup". https://claude.ai/code/session_01LV2F6VAyLq2cZexnxSprkw
The hook was working with "startup" matcher. Reverting the change to empty string which broke hook execution. https://claude.ai/code/session_01LV2F6VAyLq2cZexnxSprkw
Refactored hook to extract _has_api_key() for testability. Empty string env vars (from MCP client env blocks) are now explicitly treated as missing. Added 11 tests covering: - Config file: found, commented, empty value, missing, no key - Env var: real value, empty string, unset - Fallthrough: empty env + config file, empty env + no config https://claude.ai/code/session_01LV2F6VAyLq2cZexnxSprkw
Moved Path.home() from module-level to lazy resolution inside functions. Wrapped _has_api_key() call in try/except so any unexpected error falls through to the warning message instead of crashing the hook silently. https://claude.ai/code/session_01LV2F6VAyLq2cZexnxSprkw
Reverted to a minimal hook close to the original working version. Added config file check as a simple inline fallback instead of extracted functions. Simplified tests to call main() directly. https://claude.ai/code/session_01LV2F6VAyLq2cZexnxSprkw
The SessionStart hook was unreliable and added complexity. The MCP server already returns a clear error from every tool when no API key is configured. Updated that error message to mention the config file path (~/.config/mcp-outline/.env). - Deleted hooks/ directory (hooks.json + check_outline_config.py) - Deleted tests/test_session_hook.py - Updated error message in OutlineClient to mention config file - Removed hooks references from docs/registries.md https://claude.ai/code/session_01LV2F6VAyLq2cZexnxSprkw
Load .mcp-outline.env from the working directory before the user-level ~/.config/mcp-outline/.env. This lets users connect to different Outline instances per project/repo. Priority: env vars > .mcp-outline.env (project) > ~/.config (user) https://claude.ai/code/session_01LV2F6VAyLq2cZexnxSprkw
In stdio mode, exit with a clear error message at startup if no OUTLINE_API_KEY is available from env vars or dotenv files. SSE/HTTP modes skip this check since they support per-request keys via headers. https://claude.ai/code/session_01LV2F6VAyLq2cZexnxSprkw
Claude Code doesn't surface stderr output from MCP servers — it only shows a generic "Error with MCP Server" message. By removing the sys.exit(1) fail-fast, the server starts normally and the existing tool-level error handling in OutlineClient surfaces the clear configuration instructions when a tool is actually called. https://claude.ai/code/session_01LV2F6VAyLq2cZexnxSprkw
Explicitly document the difference: stdio has no per-request header fallback so tools return OutlineClientError, while SSE/HTTP supports per-request auth via x-outline-api-key header. https://claude.ai/code/session_01LV2F6VAyLq2cZexnxSprkw
- client-setup.md: remove session hook reference, note tool-level errors - README.md: clarify OUTLINE_API_KEY is required for tool calls (not startup) - configuration.md: explain stdio starts without key but tools return errors https://claude.ai/code/session_01LV2F6VAyLq2cZexnxSprkw
The error message was rewritten to reference dotenv config files but dropped the per-request header authentication option, which is used by SSE/HTTP transport users. https://claude.ai/code/session_01LV2F6VAyLq2cZexnxSprkw
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Dotenv configuration: Load settings from project-level
.mcp-outline.envand user-level~/.config/mcp-outline/.env.Empty
OUTLINE_*env vars (common with Claude Code's env block)are stripped so dotenv values can fill them. Existing env vars
always take priority.
Plugin & registry metadata: Added
.claude-plugin/,.mcp.json,server.json, andglama.jsonfor discoverability in Claude Code,VS Code, Glama, and the official MCP registry. Includes a GitHub
Actions workflow for MCP registry publishing.
Docs refresh: README install section with one-click buttons,
new
docs/registries.mdreference, expandeddocs/client-setup.mdwith Claude Code plugin instructions.
Config loading order
OUTLINE_*env vars from process environment.mcp-outline.envfrom current working directory~/.config/mcp-outline/.envfrom user homeoverride=False)New dependency
python-dotenv>=1.0.0Test plan
tests/test_dotenv_config.pycovers config file loading,empty var stripping, and priority ordering
ruff checkandruff format --checkclean