Skip to content

Configuration

The server validates its configuration and Gmail access before starting either transport. Missing or invalid configuration, unreadable credentials, failed delegation, and failed Gmail requests stop startup with a nonzero exit code. Errors and logs go to stderr; stdout is reserved for MCP stdio.

CLI and environment variables

Run python -m justpen_integration_mcp --help for CLI help. From a development checkout, prefix the command with uv run.

CLI option Environment variable Default Accepted values
JUSTPEN_CONTAINER_HOME ~/.justpen Nonempty filesystem path; ~ expands and relative paths resolve from the working directory.
--transport INTEGRATION_MCP_TRANSPORT stdio stdio or http.
--host INTEGRATION_MCP_HOST 127.0.0.1 IP address or hostname, without a URL scheme or port.
--port INTEGRATION_MCP_PORT 8932 Integer from 1 to 65535.
--log-level INTEGRATION_MCP_LOG_LEVEL INFO DEBUG, INFO, WARNING, ERROR, CRITICAL, NOTSET; aliases WARN and FATAL are accepted. Case-insensitive.

Precedence is CLI > environment > default, independently for each setting. Validation applies to the effective values, including host and port in stdio mode. An explicit CLI value replaces the corresponding environment value before validation. Empty environment values are invalid. --help works without valid configuration or credentials.

There is no separate integrations-file path setting: its location is always <JUSTPEN_CONTAINER_HOME>/integrations.json.

Directories and integrations.json

Startup creates the home directory and its gmail child if they do not exist. New directories request owner-only permissions, subject to platform behavior. Existing permissions and file contents are left in place. Startup does not generate integrations.json or a service-account key.

With the default home, the layout is:

~/.justpen/
├── integrations.json
└── gmail/
    └── service-account.json

The minimal valid configuration is:

{
  "email": {
    "delegated_user": "[email protected]"
  }
}

Its expanded form is:

{
  "email": {
    "type": "gmail",
    "service_account_json_path": "gmail/service-account.json",
    "delegated_user": "[email protected]"
  }
}
JSON field Required Default / validation
email Yes Object containing the Gmail integration.
email.type No gmail; other providers are rejected.
email.service_account_json_path No gmail/service-account.json, resolved beneath the configured home. Must refer to a readable, valid service-account key file.
email.delegated_user Yes Valid email address for the Google Workspace mailbox to impersonate.

Unknown JSON fields are rejected, including misspellings. The file must contain valid UTF-8 JSON. Relative credential paths resolve beneath the configured home; absolute paths are used directly and explicit ~ paths expand to the user home. Changing JUSTPEN_CONTAINER_HOME therefore relocates both default file paths. Configuration is loaded once. Restart the server after configuration or credential-file changes.

Gmail access validation

Enable the Gmail API and configure the service account for Google Workspace domain-wide delegation. An administrator must authorize this OAuth scope:

https://www.googleapis.com/auth/gmail.readonly

The delegated user must have an accessible Gmail mailbox. A service-account key by itself does not grant access to a personal Gmail inbox or to arbitrary Workspace mailboxes.

Startup creates one delegated Gmail client and calls users.getProfile with userId="me". This verifies token issuance, delegation, scope and actual mailbox API access without fetching message content. Only after that succeeds does the MCP transport start. Token refresh is automatic through Google Auth; all tool calls reuse the client and the connection closes on shutdown.

Authentication failures, HTTP rejections and network failures have distinct error prefixes. Raw Google error bodies, tokens and private keys are not included in application error messages. Startup validation is a point-in-time check; revoked permissions or later network failures can still make tool calls fail.

Requests have a 10-second socket inactivity timeout. The startup operation has a 30-second budget, and each tool operation has a 60-second budget including queue time. Expired calls issue no further requests. An already running synchronous request cannot be forcibly interrupted: cleanup waits for it before closing the client, so these budgets are not hard process-exit deadlines. The client serializes Gmail operations because its HTTP transport is not thread-safe; this does not block the MCP event loop.

Stdio

python -m justpen_integration_mcp

Example MCP client configuration, using the Python environment where the server is installed:

{
  "mcpServers": {
    "justpen-integration": {
      "command": "python",
      "args": ["-m", "justpen_integration_mcp"],
      "env": {
        "JUSTPEN_CONTAINER_HOME": "/absolute/path/to/justpen-home"
      }
    }
  }
}

Omit the env block to use ~/.justpen.

HTTP

python -m justpen_integration_mcp --transport http

Connect an MCP client using Streamable HTTP at http://127.0.0.1:8932/mcp. The equivalent environment setting is INTEGRATION_MCP_TRANSPORT=http. To choose another bind address and port:

python -m justpen_integration_mcp --transport http --host 127.0.0.1 --port 9000

HTTP serves the same tools and delegated mailbox as stdio. It has no built-in client authentication. The default bind address limits access to the local machine. If you expose it beyond that machine, put access control and TLS in front of it; callers can search the configured mailbox.