Go MCP timestamping server + pkg/tsnats (sibling to Python server)
  • Go 96.6%
  • Shell 3.4%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
George Lambert 369f9210bd
Some checks failed
test-and-deploy / test (push) Failing after 12m11s
test-and-deploy / deploy-138 (push) Has been cancelled
fix(auth): clear public write errors and Grok client path
Public DEC-654 still requires a caller bearer; anonymous session now
returns that guidance as a tool error instead of silent valid:false.
Error text names JWT and API key, Grok bearer_token_file, and local
stdio. BearerFromRequest also accepts X-Api-Key / X-Verae-Key.
Document Grok stdio vs public URL; add scripts/sync-mcp-bearer.sh.
2026-10-12 14:09:22 -04:00
.forgejo/workflows Add an ns1 test-and-deploy workflow for the Go MCP server. 2026-10-11 05:52:17 +00:00
cmd/verae-mcp-timestamping-server D write-only lockdown (DEC-654): public HTTP server needs the caller's own Verae key/OAuth bearer for stamp (any scope), signup, create_user, session; login refused; no host-login fallback for writes; anonymous verify/hash_report kept, rate limited 30/min per client (burst 15), 600/min overall 2026-10-10 13:06:57 -04:00
deploy chore: shadow systemd unit and parity smoke script 2026-09-29 12:14:46 -04:00
docs docs: L5/L7 PASS after laptop VeraeTime login refresh 2026-09-29 12:33:19 -04:00
examples/tsnats-bulk docs: cutover checklist and tsnats usage 2026-09-29 12:14:46 -04:00
internal fix(auth): clear public write errors and Grok client path 2026-10-12 14:09:22 -04:00
pkg feat: pkg/tsnats digests-only NATS timestamp client 2026-09-29 11:52:35 -04:00
scripts fix(auth): clear public write errors and Grok client path 2026-10-12 14:09:22 -04:00
.gitignore feat: module scaffold and digest normalize/guard 2026-09-29 11:43:22 -04:00
go.mod feat: embedded NATS with VeraeTime handlers and stdio MCP 2026-09-29 12:11:47 -04:00
go.sum feat: embedded NATS with VeraeTime handlers and stdio MCP 2026-09-29 12:11:47 -04:00
README.md fix(auth): clear public write errors and Grok client path 2026-10-12 14:09:22 -04:00

verae-mcp-timestamping-server-go

standard-readme compliant

Go MCP timestamping server for Verae. Digests only; sibling to the Python server.

Implements the same tools as https://mcp.verae.ai/mcp (stamp, verify, hash_report, auth tools) using the official MCP Go SDK. Designed for shadow deploy beside Python, then cutover.

AI assistants use MCP. Bulk app workers can import pkg/tsnats for core NATS request/reply on verae.ts.* (job-complete stays ephemeral; no JetStream for those events). Cutover steps: docs/cutover.md.

Table of Contents

Install

cd verae-mcp-timestamping-server-go
go build -o bin/verae-mcp-timestamping-server ./cmd/verae-mcp-timestamping-server

Requires Go 1.26+. Design: docs/superpowers/specs/2026-09-29-go-mcp-timestamping-server-design.md. The ns1 unit verae-mcp-timestamping.service runs this binary from /opt/verae/verae-mcp-timestamping-server-go/bin. .forgejo/workflows/test-and-deploy.yml tests on the 138 runner and scripts/deploy-138.sh swaps that binary, with a probe of http://127.0.0.1:8000/mcp and rollback to the previous file.

Usage

Shadow beside Python (:8000 stays live):

VERAE_MCP_TRANSPORT=streamable-http \
VERAE_MCP_HOST=127.0.0.1 \
VERAE_MCP_PORT=8001 \
VERAE_NATS_LISTEN=127.0.0.1:4223 \
VERAE_MCP_REQUIRE_BEARER=0 \
./bin/verae-mcp-timestamping-server

Point MCP clients at http://127.0.0.1:8001/mcp. For stdio: -transport stdio or VERAE_MCP_TRANSPORT=stdio.

Variable Default Notes
VERAE_MCP_TRANSPORT streamable-http or stdio
VERAE_MCP_HOST 127.0.0.1 HTTP bind
VERAE_MCP_PORT 8000 shadow examples use 8001
VERAE_NATS_LISTEN 127.0.0.1:4223 embedded NATS; set empty to disable
VERAE_MCP_REQUIRE_BEARER 0 0 = host-token keeper when no caller bearer; 1 = require caller bearer
VERAE_GLOBAL_URL https://api.veraetime.net
VERAE_AUTH_PROPERTIES $HOME/.verae/auth.properties
VERAE_GLOBAL_TOKEN empty optional static host bearer
VERAE_LEDGER_PATH $HOME/.verae/mcp-timestamp-local.json
VERAE_MCP_CORS off set 1 for browser CORS

Global stamps use VeraeTime with auth from auth.properties (or caller Bearer). Embedded NATS serves verae.ts.*; job-complete is core verae.ts.completed only.

Public HTTP vs local stdio (DEC-654)

Transport Writes
Public HTTP (mcp.verae.ai, default streamable-http) Caller must send Authorization: Bearer <JWT or API key> on every tools/call. No host-login fallback.
Local stdio (-transport stdio) Host login from ~/.verae/auth.properties is used when no caller bearer is sent.

Grok Build CLI

Option A — local stdio (recommended for laptop agents): host auth, no public lockdown.

# ~/.grok/config.toml
[mcp_servers.verae-timestamping]
command = "/absolute/path/to/bin/verae-mcp-timestamping-server"
args = ["-transport", "stdio"]
enabled = true

[mcp_servers.verae-timestamping.env]
VERAE_NATS_LISTEN = ""

Option B — public URL with caller bearer:

./scripts/sync-mcp-bearer.sh   # writes ~/.verae/mcp-bearer from auth.properties
[mcp_servers.verae-timestamping]
url = "https://mcp.veraetime.net/mcp"
enabled = true
bearer_token_file = "~/.verae/mcp-bearer"

Reconnect the MCP server after config changes (new Grok session or /mcps toggle).

Parity smoke when Python :8000 and Go :8001 are both up:

./scripts/parity_smoke.sh

pkg/tsnats

Bulk workers talk to the embedded (or any) NATS URL. Digests only; SubscribeCompleted is core NATS, not JetStream.

package main

import (
	"context"
	"log"
	"os"

	"git.georgelambert.org/marchon/verae-mcp-timestamping-server-go/pkg/tsnats"
)

func main() {
	url := os.Getenv("NATS_URL")
	if url == "" {
		url = "nats://127.0.0.1:4223"
	}
	client, err := tsnats.Connect(url)
	if err != nil {
		log.Fatal(err)
	}
	defer client.Close()

	ctx := context.Background()
	digest := "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
	receipts, err := client.Stamp(ctx, digest, tsnats.StampOptions{Scope: "global"})
	if err != nil {
		log.Fatal(err)
	}
	log.Printf("receipts: %+v", receipts)
}

Runnable sketch: examples/tsnats-bulk/main.go.

Contributing

Questions: this research workspace / marchon@gmail.com. PRs coordinated in-workspace first. Protocol questions: https://github.com/modelcontextprotocol.

License

UNLICENSED © George Lambert