npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@sema-agent/connector-gitea

v0.1.10

Published

Gitea connector: runs the pinned gitea-mcp release behind the sema-connector launcher, with its personal access token delivered as a file.

Readme

Gitea connector

@sema-agent/connector-gitea (CN-037) connects the engine to a Gitea instance with a personal access token. It runs gitea-mcp, the Gitea project's own MCP server, unmodified behind the sema-connector launcher, at the version and sha256 its binaries.lock.json pins. The launcher's stages (scope, normalize, status, trace, the withholding of secret values) apply to it as to every connector; see ARCHITECTURE.md. A hand-written connectors/gitea/tools.json narrows which of its tools a caller may use (the standalone per-tool policy, CN-054, ARCHITECTURE.md, "Stages on the launcher hop"); absent, every tool is granted. Its bin is sema-connector-gitea; its subcommands are the shared CLI kit's (CN-039) around the shared install of a pinned upstream program (CN-044) and this package's auth, and read the configuration directory from CONFIG_LOCAL_DIR like every connector's (INTEGRATION-SERVER.md).

Setting it up

export CONFIG_LOCAL_DIR=/absolute/path/to/the/engine/configuration
sema-connector-gitea install
sema-connector-gitea auth < gitea-auth.json     # one line: {"host": "...", "token": "..."}
sema-connector-gitea mount
sema-connector-gitea status

Then restart the engine. Write gitea-auth.json with an editor as a file only you can read, and delete it after auth: a token on a command line (an echo or printf argument) is visible to other processes.

The pinned build

binaries.lock.json is the one place that names the gitea-mcp build, in the shape "Pinned upstream programs" in ARCHITECTURE.md describes: the key gitea-mcp, version 1.8.1, four archives, one for each platform, each from https://gitea.com/gitea/gitea-mcp/releases/download/v{version}/{file}, pinned with the sha256 the release's checksums.txt gives for it and unpacked as its one entry gitea-mcp ({"entry": "gitea-mcp"}), which is the program ({"binary": "gitea-mcp"}).

install

install is the shared install of a pinned upstream program (see "Pinned upstream programs" in ARCHITECTURE.md): it fetches this platform's archive, compares its sha256 with the lock before anything is written, and keeps the archive and its gitea-mcp entry in <configuration directory>/connectors/gitea/bin/ (the directory 0700, gitea-mcp 0755). When that directory already holds the pinned build, install changes nothing.

auth

auth reads exactly one line from standard input (never from an argument), a JSON object with exactly two string members:

{"host": "https://gitea.example.com", "token": "<personal access token>"}
  • host is an https URL, or an http URL on 127.0.0.1 or localhost (the host rule; see "Secrets", "host rule" in ARCHITECTURE.md — the shared layer's one rule for a connector's host, the rule the launcher also holds a key set URL to, and the one the GitHub connector's optional GitHub Enterprise Server host shares, CN-045), without credentials, query or fragment. A path is kept (a Gitea served under /gitea); a trailing slash is dropped.
  • token is printable ASCII without spaces.
  • Any other key, a key given twice, or a value that is not a string is refused, and a refusal never repeats what was read (the shared CLI kit's readStdinJson).

The two values are stored through the secrets backend as the handles GITEA_HOST and GITEA_TOKEN: 0600 files in <configuration directory>/connectors/gitea/ (0700). The host is not part of the catalog entry (an entry never carries environment references), so it is kept as a handle next to the token, and it is not a secret: it is stored with the metadata {"secret": false}, so the launcher delivers it like the token but does not withhold the many Gitea answers that carry addresses on the host, and the status counts only the token (see "Secrets" in ARCHITECTURE.md).

auth writes the two handles as one group under the lock of the connector's directory, connectors/gitea/.auth.lock, which every launch of the connector also holds while it copies the handles: a connector started while auth runs gets the old pair or the new pair, never the new host with the old token. While another process holds the lock, auth waits up to 5 seconds and then refuses, changing nothing. Only the holder removes the lock; one left by a process that died is removed by hand (nothing guesses that a lock is stale). Inside the group auth removes the stored token first and only then writes the host and the token, so an auth that fails or ends halfway leaves no token at all, never one auth's token next to another's host, and never a new token paired with an unwritten host. A handle always has a value (a secret value is never the empty string, see "Secrets" in ARCHITECTURE.md); taking the token away is remove, not a put of an empty string. With no token the status is unauthorized, the launcher never starts the connector (see "Parked session" in ARCHITECTURE.md), and a tool call through the launcher is refused with connector.auth_required: auth again stores a fresh pair.

mount and status

mount writes the connector's standalone catalog entry through the shared mount function, and status prints the status the launcher serves, as for every connector. Before auth there is no token (the host alone is not a secret), so the launcher does not start the connector and answers itself (see "Parked session" in ARCHITECTURE.md): status prints {"state":"unauthorized","tools":[]} and exits 0, and a tool call through the launcher is refused with connector.auth_required. Once auth has stored the token, the status lists the tools gitea-mcp reports, so it needs gitea-mcp running: before install the connector cannot start it, and status exits 1 with what the connector said, which names the subcommand to run.

unmount removes that entry again and list prints the connectors mounted in the configuration directory, through the shared unmount and listMounted (@sema-agent/connectors 0.9.0, CN-065); an entry under this connector's name that is not exactly what mount writes is refused and left alone, and never listed (KNOWN-LIMITS.md, KL-32).

What runs

With no arguments, sema-connector-gitea is the connector process the launcher starts. It starts the pinned gitea-mcp as its child on the same standard input, output and error, so every MCP message passes between the launcher and gitea-mcp untouched, and it ends as gitea-mcp ends: with its exit code, or by the signal that ended it (the launcher then reports the connector's outcome as for any connector, exit 5 when abnormal). The stop signals the connector receives are passed on to gitea-mcp.

The launcher names the connector's directory in CONNECTOR_DIR (see "Connector process environment" in ARCHITECTURE.md). The connector refuses to start gitea-mcp (exit 1, with a line on stderr naming what to do) on the shared start check ("Pinned upstream programs": without CONNECTOR_DIR, without both handles, when the handle paths are not regular files in CONNECTOR_DIR, when bin/ in CONNECTOR_DIR does not hold the pinned build), and when the stored host is outside the host rule or the stored token is empty.

gitea-mcp gets no arguments and the environment the launcher gave the connector with CONNECTOR_DIR and the two handle paths replaced by what gitea-mcp reads:

  • GITEA_HOST: the stored host;
  • GITEA_ACCESS_TOKEN_FILE: the path of the launcher's per-launch copy of the token;

and with HOME set to its own home in the connector's directory, <CONNECTOR_DIR>/home (CN-040; "Pinned upstream programs" in ARCHITECTURE.md).

No other gitea-mcp setting reaches it (such as GITEA_ACCESS_TOKEN, MCP_MODE, GITEA_INSECURE, GITEA_TOOLS or a proxy variable), since the launcher passes none of them to the connector.

Where the token goes

The token is a 0600 file in the configuration directory. The launcher reads it before the connector starts and hands the connector a per-launch copy; the connector passes on only that copy's path, and gitea-mcp reads the file itself and sends the token to the stored host in its Authorization header. The connector process never reads the token. The token is never in an argument, in the value of an environment variable, in the catalog entry or in the status; the launcher withholds any reply of gitea-mcp that carries it and replaces it in gitea-mcp's stderr.

Outbound connections

gitea-mcp is given one address, the stored host, and no proxy setting. The standalone form has no egress proxy (that is M3), so whether it connects anywhere else is gitea-mcp's own behaviour: the negative-control gate (run-gitea-negctl-test) runs the pinned build under a sandbox that refuses every other connection, and fails on any attempt it reports; when the host stops delivering the reports of an executable the gate cannot see those attempts (KL-28; see KNOWN-LIMITS.md, shipped with this package and, in the repository, docs/KNOWN-LIMITS.md).

Known limits

  • gitea-mcp keeps its own log in its home, <CONNECTOR_DIR>/home/.gitea-mcp/gitea-mcp.log (CN-040: in the configuration directory, never in the user's home), outside the launcher's stderr and its replacement of secret values; it holds gitea-mcp's tool errors, which can name URLs and user names of the Gitea server, and nothing removes it (KL-25).
  • Redirects: gitea-mcp follows up to ten redirects of a GET, to wherever the Gitea server sends it.
  • Check, then start: as for every pinned upstream program (see "Pinned upstream programs" in ARCHITECTURE.md).