Skip to content

feat: dotenv config files and plugin registry support#75

Merged
Vortiago merged 34 commits intomainfrom
claude/mcp-plugin-planning-MYKTV
Mar 5, 2026
Merged

feat: dotenv config files and plugin registry support#75
Vortiago merged 34 commits intomainfrom
claude/mcp-plugin-planning-MYKTV

Conversation

@Vortiago
Copy link
Owner

@Vortiago Vortiago commented Mar 3, 2026

Summary

  • Dotenv configuration: Load settings from project-level
    .mcp-outline.env and 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, and glama.json for 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.md reference, expanded docs/client-setup.md
    with Claude Code plugin instructions.

Config loading order

  1. Strip empty OUTLINE_* env vars from process environment
  2. Load .mcp-outline.env from current working directory
  3. Load ~/.config/mcp-outline/.env from user home
  4. Pre-existing (non-empty) env vars always win (override=False)

New dependency

python-dotenv>=1.0.0

Test plan

  • New tests/test_dotenv_config.py covers config file loading,
    empty var stripping, and priority ordering
  • Unit tests pass — 398 passed
  • Lint/format pass — ruff check and ruff format --check clean
  • Type check passes — pyright 0 errors

claude added 6 commits March 3, 2026 22:01
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
@Vortiago Vortiago force-pushed the claude/mcp-plugin-planning-MYKTV branch from 1212668 to e4ff803 Compare March 4, 2026 11:15
claude added 23 commits March 4, 2026 12:18
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
claude added 5 commits March 5, 2026 07:40
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
@Vortiago Vortiago changed the title Add Claude Code plugin support and MCP Registry publishing feat: Add Claude Code plugin support and MCP Registry publishing Mar 5, 2026
@Vortiago Vortiago changed the title feat: Add Claude Code plugin support and MCP Registry publishing feat: dotenv config files and plugin registry support Mar 5, 2026
@Vortiago Vortiago merged commit 4b58018 into main Mar 5, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants