Skip to content

ghchinoy/eldamo-elvish-lexicon

v0.2.0Apache-2.0

Tolkien Elvish lexicon MCP tools and linguistic agent skills over Paul Strack's Eldamo compilation

🌟 Eldamo Agent Tools 🌟

License GitHub release Build & Test

A high-performance, dual-protocol agent server written in Go, providing AI agents with immediate, structured, linguistic access to Paul Strack's Eldamo Tolkien language lexicon compilation. A single binary speaks both:

  • MCP (Model Context Protocol) β€” the transactional surface: stateless tool calls (search, lookups, derivations, TTS) at /sse.
  • A2A (Agent2Agent) β€” the interactional surface: agentic skills (name generation, translation, neologisms) at /a2a.

Both protocols are mounted on the same net/http mux, gated by the same OAuth 2.1 JWT layer, and read the same in-memory lexicon loaded once at startup. The mental model: MCP exposes the tools; A2A exposes the agent that uses them.

The server is designed for portability and serverless agility: it can be run locally as a native desktop service via either the prebuilt binaries or built from source, or deployed securely as a multi-user, OAuth-gated remote server on Google Cloud Run.

This repository bundles the MCP Server, the A2A agent surface, and a set of Linguistic Agent Skills for Tolkien linguistic tasks (translation, name generation, and neologism composition).

It features a secure, modern (2026-standard) OAuth 2.1 Authentication Layer utilizing Client ID Metadata Documents (CIMD), Firebase Auth, and GCP Cloud Run.


πŸš€ Quick Start (Local Dev Server)

Get a local Eldamo server running on your machine in under 30 seconds:

# 1. Clone the repository (requires Go 1.25.5+)
git clone https://github.com/ghchinoy/eldamoapi.git
cd eldamoapi

# 2. Start the server in local Auth Bypass mode
make run-dev

The server will listen on http://127.0.0.1:8080 with AUTH_BYPASS=true. You can then point your local agent (e.g. OpenCode) to http://127.0.0.1:8080/sse. See the Developer Guide for full compilation and testing workflows.

πŸ“– Table of Contents

  1. Quick Start (Local Dev Server)
  2. Exposed MCP Tools, Prompts & Resources
  3. A2A Agent Surface
  4. Linguistic Agent Skills
  5. One-Line Installation (Prebuilt Binary)
  6. Client Configurations
  7. System Architecture & Deployment Overview
  8. Environment Variables & Configuration
  9. Cloud Run Deployment
  10. Documentation Index
  11. Contributing & Development

πŸ› οΈ Exposed MCP Tools, Prompts & Resources

The server exposes specialized tools, workflow prompts, and read-only resources conforming to the Model Context Protocol specification. All read tools carry readOnlyHint: true annotations and feature dual-emit results (returning both markdown/text content and typed JSON structuredContent matching published outputSchemas).

πŸ› οΈ Tools

  1. enquire_lexicon (Title: "Search Lexicon")
    • Performs general-purpose Tolkien linguistic search across prefix spellings and keyword glosses.
    • Arguments: query (required), language, speech, category
  2. get_word_details (Title: "Word Details")
    • Fetches complete linguistic metadata, historical notes, inflections, and semantic details for an entry.
    • Arguments: id (required page-id)
  3. get_derivations (Title: "Derivation Tree")
    • Explores the genealogical evolution of words (ancestors or descendants).
    • Arguments: id (required page-id), direction ("descendants" or "ancestors")
  4. get_root_anchors (Title: "Root Anchors")
    • Retrieves proper names (characters, places, stars, weapons) derived from a root ID.
    • Arguments: id (required page-id)
  5. render_elvish_audio (Title: "Pronounce Elvish", conditional)
    • Synthesizes audio pronunciation via Kokoro-based TTS when ELVISH_TTS_URL is set.

πŸ“ Prompts

Standard MCP workflow prompts sharing single-source instructions with our A2A skills:

  • tolkien-translation: Guided translation workflow prompt into Quenya or Sindarin.
  • tolkien-name-generator: Guided name generation prompt with compounding rules and suffixes.
  • neologism-builder: Guided neologism coining prompt with two-path choices and 100-point rubric.

πŸ“¦ Resources

  • eldamo://agent-card: Returns the JSON AgentCard metadata describing agent capabilities.
  • eldamo://lexicon/stats: Returns summary JSON statistics (total words, keyword indices) for the in-memory index.

🀝 A2A Agent Surface

Alongside MCP, the server exposes an A2A (Agent2Agent) endpoint so other agents can delegate tasks (not just call tools) to the Eldamo agent. This is the interactional counterpart to MCP's transactional tools.

  • AgentCard (public discovery): GET /.well-known/agent-card.json
  • Protocol endpoint (auth-gated): POST /a2a (JSON-RPC; SSE for streaming)
  • Auth: the same Bearer JWT used for MCP. A2A clients pass it as Authorization: Bearer ….

Status: All four A2A skills are live: name-generate (deterministic), neologism (LLM, two-path), translate (LLM, streaming), and echo (diagnostic). The agent is served at https://candir.mithlond.com/a2a.

Quick test with a2acli

# Discover the agent (public, no auth)
a2acli discover --service-url https://candir.mithlond.com

# Token β€” always set -a first so JWT_SIGNING_KEY reaches child processes
set -a; source .env; set +a

# Name generation (deterministic)
a2acli send "name star silver quenya" \
  --service-url https://candir.mithlond.com --transport jsonrpc --wait \
  --token "$(make token)"

# Translation (LLM-backed, streaming)
a2acli send "translate farewell my friend to quenya" \
  --service-url https://candir.mithlond.com --transport jsonrpc --wait \
  --token "$(make token)"

# Neologism (LLM, two artifacts)
a2acli send "neologism hover-board quenya" \
  --service-url https://candir.mithlond.com --transport jsonrpc --wait \
  --token "$(make token)"

Full procedures and the auth matrix are in the Test Plan.

🧠 Linguistic Agent Skills

This repository bundles specialized linguistic agent skills within the skills/ directory, assisting agents to approach complex, artistic, and precise Elvish linguistic tasks:

1. neologism-builder

  • TL;DR: Guides the creation of Neo-Elvish vocabulary. Offers a choice between Practical (Functional) compounding and Poetic (Metaphorical) concepts, evaluated via a 100-point Quantitative Scoring Matrix that balances strict phonetic constraints against acoustic iconicity and proper-noun lineage, derived in part from The Digital Tolkien Project's arda pronunciation library.

2. tolkien-name-generator

  • TL;DR: Autonomously generates grammatically and historically-based Tolkien Elvish names for people, places, stars, or weapons. Compounds linguistic roots using proper Sandhi consonant merges and applies attested suffix paradigms.

3. tolkien-translation

  • TL;DR: Translates English phrases into Tolkien's main languages (Quenya, Sindarin, and AdΓ»naic). Analyzes sentence grammar, verb conjugations, adjective agreements, and case morphology, ensuring appropriate historical dialect selection.

🧩 Agent Plugins Specification v1.0.0

This repository is packaged as a conformant Agent Plugin:

  • plugin.json: Root manifest declaring metadata, capabilities, and schema (https://agent-plugins.org/schemas/1.0.0/plugin.schema.json).
  • mcp.json: MCP configuration declaring the remote Streamable HTTP endpoint (https://candir.mithlond.com/sse).
  • skills/: Standard directory containing SKILL.md workflow documents conforming to Agent Skills.

πŸ’Ύ One-Line Installation (Prebuilt Binary)

For users who do not wish to clone the repository or compile from source, you can install the latest prebuilt eldamoapi binary automatically to /usr/local/bin:

curl -sL https://raw.githubusercontent.com/ghchinoy/eldamoapi/main/scripts/install.sh | bash

The eldamoapi binary is an HTTP server (it speaks Streamable HTTP/SSE, not stdio). Start it locally in auth-bypass mode:

AUTH_BYPASS=true eldamoapi

Once running on http://127.0.0.1:8080, configure your desktop agent to connect over HTTP/SSE:

A. Configure for opencode

Add this to your global ~/.config/opencode/opencode.json or local workspace opencode.json:

{
  "$schema": "https://opencode.ai/config.json",
  "skills": {
    "paths": ["skills"]
  },
  "mcp": {
    "eldamo-local": {
      "type": "remote",
      "url": "http://127.0.0.1:8080/sse",
      "enabled": true
    }
  }
}

B. Configure for Claude Desktop

Add this to your claude_desktop_config.json file:

{
  "mcpServers": {
    "eldamo-local": {
      "type": "remote",
      "url": "http://127.0.0.1:8080/sse"
    }
  }
}

⚑ Client Configurations

To add your remote, secure Eldamo MCP server to your desktop agent, follow the configurations below.

Note

Detailed information regarding the OAuth 2.1 & CIMD security flow, and our Firestore-based access control, can be found in our Architecture Documentation.

1. opencode

Configure the server in your local or global opencode.json file:

Project-Specific Config (Local)

Create an opencode.json file in the root of your local workspace directory:

{
  "$schema": "https://opencode.ai/config.json",
  "skills": {
    "paths": ["skills"]
  },
  "mcp": {
    "eldamo-remote": {
      "type": "remote",
      "url": "https://candir.mithlond.com/sse",
      "enabled": true,
      "oauth": {
        "clientId": "https://www.mithlond.com/metadata.json",
        "authorizationUrl": "https://www.mithlond.com/mcp-auth",
        "tokenUrl": "https://candir.mithlond.com/api/oauth/token"
      }
    }
  }
}

Tip

The "skills": { "paths": ["skills"] } block is essential to enable OpenCode to discover and load the bundle of Linguistic Agent Skills (like the neologism-builder) included in the project directory.

Global Config (Universal)

Add the server block to your global configuration file at ~/.config/opencode/opencode.json:

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "eldamo-remote": {
      "type": "remote",
      "url": "https://candir.mithlond.com/sse",
      "enabled": true,
      "oauth": {
        "clientId": "https://www.mithlond.com/metadata.json",
        "authorizationUrl": "https://www.mithlond.com/mcp-auth",
        "tokenUrl": "https://candir.mithlond.com/api/oauth/token"
      }
    }
  }
}

Important

Always quit and restart opencode after saving configuration changes for the remote MCP server to take effect.


πŸ—οΈ System Architecture & Deployment Overview

The Eldamo MCP Server is engineered for zero-dependency portability and stateless scale-to-zero serverless environments.

Key Architectural Pillars:

  • Dual-Protocol, Single Binary: MCP (/sse, transactional tools) and A2A (/a2a, interactional skills) share one net/http mux, one OAuth gate, and one lexicon index β€” no second service to deploy. See Dual-Protocol Architecture.
  • Gzip Embed Engine (go:embed): Paul Strack's complete 24.8MB flat XML lexicon is preprocessed and embedded directly inside the statically compiled Go binary as a highly compressed gzip dataset (~4.5MB).
  • Double-Index Search Engine: On startup, the server decompresses the dataset in under 20ms and constructs in-memory prefix tries and inverted keyword indexes, allowing sub-millisecond search query latencies.
  • Low-Footprint Serverless Deployment: The entire active runtime (tries, indices, and streamable multiplexers) consumes only ~40-50MB of RAM, allowing us to deploy to cheap Google Cloud Run container instances.
  • Stateless Security Gateway: Authentication is anchored on OAuth 2.1 and Client ID Metadata Documents (CIMD), issuing signed stateless JWTs (MITHLOND_ACCESS_TOKEN). No database checks are executed during active tool/skill queries.

For the dual-protocol design, see Dual-Protocol Architecture. For a deep technical dive into the OAuth/CIMD patterns, Firestore schemas, the loopback-agnostic callback matching (RFC 8252), or infrastructure hardening blueprints, see the Detailed Architecture & Design Notes. For testing procedures, see the Test Plan.

βš™οΈ Environment Variables & Configuration

Local configurations are managed in a .env file at the project root. This file is excluded from Git to protect sensitive credentials.

The backend uses the following environment variables, evaluated with fallback/precedence logic:

Variable NamePurposeFallback / Precedence Logic
GCP_PROJECTGoogle Cloud project ID.Sourced from .env; defaults to testingproject-19c4c during build.
GCP_REGIONCloud Run deployment region (gcloud run deploy --region).Sourced from .env; defaults to us-central1. Not passed to the container.
SERVICE_NAMECloud Run deployment name.Sourced from .env; defaults to eldamo-mcp-server.
FIREBASE_PROJECT_IDProject ID for Firebase Admin verification.Matches GCP_PROJECT. Defaults to testingproject-19c4c.
FIREBASE_DATABASETargets specific Firestore DB instance.Sourced from .env; defaults to mithlond-services (NOT (default)).
JWT_SIGNING_KEYCryptographic key to sign/verify stateless tokens.Sourced from .env; dynamically generated as a random 32-char hex string on first deploy if missing.
GEMINI_LOCATIONVertex AI API location for Gemini skills. Separate from GCP_REGION β€” newer models (gemini-3.x) require global; older models work with us-central1.Defaults to global.
GEMINI_TRANSLATE_MODELGemini model for the translate and neologism skills. When unset, both skills self-hide from the AgentCard and executor.None β€” skills disabled if missing.

πŸš€ Cloud Run Deployment

Deployment is fully automated using our secure shell pipeline. This pipeline loads your local .env variables, ensures GCP resources are fully initialized, and compiles the service in-cloud.

# Execute deployment pipeline
./scripts/deploy.sh

For detailed deployment blueprints and IAM safety configurations, see our Architecture Documentation.

πŸ“š Documentation Index

GuideTarget Audience & Purpose
🏹 User GuideEnd-user setup guide for connecting OpenCode, Claude Desktop, Cursor, Gemini Spark, or A2A clients (a2acli) to the live service.
πŸ› οΈ Developer GuideLocal compilation, running tests (make test), linter rules, and GoReleaser release steps.
πŸ›‘οΈ Administrator's GuideManaging authorized users, scopes, and JWT token issuance via cmd/eldamo-admin.
πŸ’‘ Use Cases & ExercisesWorked linguistic examples and exercises for Elvish translation and neologism creation.
πŸ›οΈ Dual-Protocol ArchitectureIn-depth technical specification of the multiplexed MCP + A2A dual-surface architecture.
πŸ”’ Security & OAuth ArchitectureDeep dive into OAuth 2.1, CIMD discovery, PKCE, loopback redirection, and Firestore schemas.
πŸ§ͺ Test PlanVerification matrix for MCP tools, A2A skills, OAuth endpoints, and local LLM backends.
πŸ€– Local LLM ServersStanding up local llama.cpp or MLX servers for offline Gemma 4 translation and neologisms.
πŸ“Š Model EvaluationQuality, latency, and cost-per-token comparisons across Gemini and local Gemma models.
πŸŽ“ How to Build Your Own Go MCP ServerComprehensive tutorial on building high-performance Go MCP servers with OAuth 2.1.
πŸ“ Precursor Leak ResolutionHistorical design record detailing the fix for conflated derivations in the XML pipeline.

🀝 Contributing & Development

We welcome contributions to the Eldamo MCP Server and Linguistic Agent Skills! Pull requests are welcome β€” for major changes or architectural additions, please open an issue first to discuss your proposed changes.

Make sure to run unit tests (make test) and verify the linter (golangci-lint run β€” strict 0-issue bar) before submitting a PR. For local build steps, test procedures, and release workflows, see the Developer Guide.