NAME
AnyEvent::MCP::Config - named servers and derived MCP credentials
SYNOPSIS
use AnyEvent::MCP::Config;
my $config = AnyEvent::MCP::Config->global;
my $token = $config->credential ("token", "agni");
my $url = $config->http_url ("agni", undef, path => "/");
DESCRIPTION
An MCP server and its clients often need matching credentials. Rather than maintaining a separate password for each server and user, this module can derive them from one private master secret. The invoked program basename, instance name, optional username and credential purpose each contribute to the result. Instances default to default; different programs still derive different credentials for that instance name.
The shared file format is described in "GLOBAL CONFIGURATION" in AnyEvent::MCP. Loading this module does not read any files. The first call to global reads the configuration, ensures a master secret exists and caches the object for the process.
A missing secret is generated using AnyEvent::MCP::random_bytes and saved when possible. Saving failure produces a warning; the generated secret remains usable in this process, but another process might derive different credentials. A supplied invalid secret is an error. Changing or losing the master secret invalidates all credentials derived from it.
Derivation uses derive_secret with the random master key. The application namespace, purpose, program, instance name and username are separately length-prefixed, so distinct contexts derive different credentials. Deriving a password does not create an account or configure the server to accept it: authentication still belongs to the server.
METHODS
- $config = AnyEvent::MCP::Config->global (file => $file)
-
Returns the cached global configuration. The first call accepts the same arguments as
new; later calls return the same object without rereading the file. Call this explicitly during program startup. - $config = AnyEvent::MCP::Config->new (file => $file)
-
Reads
$file, or the default file when omitted, and ensures a master secret exists. Unlikeglobal, each call creates an independent object. A missing file is allowed; other read errors are fatal. Sections are available as$config->{section}{$section}, each a hash reference of string values. Named servers use[instance NAME]. - $config = AnyEvent::MCP::Config->init (file => $file)
-
Explicitly creates the configuration file with a random secret, mode 0600. Creates missing parent directories with mode 0700. Fails if the file already exists, so it cannot accidentally replace an existing secret.
- $bytes = $config->derive_secret ($length, @info)
- $bytes = AnyEvent::MCP::Config->derive_secret ($length, @info)
-
Derive
$lengthsecret bytes from the configuration's master secret and an ordered list of context byte strings@info. The class form usesglobal, loading the default configuration on first use and reusing it thereafter. The object form uses that object's configuration, including one loaded from an explicit file.The same master secret and context always produce the same bytes. Use a distinctive application/purpose string as the first context field, followed by names or other values identifying the result:
my $secret = AnyEvent::MCP::Config->derive_secret ( 32, "my application token v1", AnyEvent::MCP::utf8enc ($name) );The result contains raw bytes; encode it yourself if a printable token is needed. This method does not add the result to a server's accepted tokens.
The fixed
anyevent-mcpcontext field is prepended automatically. Context fields are separately length-prefixed, so("ab", "c")and("a", "bc")have different contexts. Encode character strings explicitly, for example withAnyEvent::MCP::utf8enc. Context arguments are left unchanged.$lengthmust be an integer in 0..16320; zero returns an empty string. Shorter results are prefixes of longer results for the same master secret and context. Use distinct context fields for different purposes, rather than relying on different lengths to separate them.Derivation uses HKDF-SHA512 expansion, with each context field prefixed by its four-byte big-endian byte length. Changing or losing the master secret changes every result derived from it.
- $credential = $config->credential ($purpose, $name, $username)
-
Derives a 32-byte credential, returned as unpadded URL-safe Base64.
$purposeistoken.$nameis the instance name, and$usernameis optional. The default server credential is derived with no username.Credentials use the context
("anyevent-mcp", "token", PROGRAM, NAME, USER). PROGRAM is the invoked basename, with a trailing.plor.perlremoved. Changing the program or instance name changes the credential. A credential derived with$usernameis not automatically accepted by the server. This method neither requires a server section nor configures authentication. - $program = AnyEvent::MCP::Config::program_name ()
-
Returns the invoked program basename, stripping
.plor.perl. An inline Perl invocation usesperl. This identity also selects the[program PROGRAM]configuration section; it is independent of routing aliases. - $name = AnyEvent::MCP::Config::server_name ($name)
-
Validate a service-instance name, or use
defaultif undefined. Names consist of an ASCII letter or underscore followed by letters, digits, underscores or hyphens. - @options = AnyEvent::MCP::Config::http_getopt (\$name, \$bind, \$print_url, \@tokens)
-
Return standard
Getopt::Longoptions referring to the caller's scalars. - $port = $config->server_port ($name)
-
Derive a stable default port in 16384..32767 from the master secret and program basename and service-instance name. Collisions produce ordinary listener bind errors.
- %settings = $config->http_settings ($name, $bind)
-
Resolve HTTP settings from
[instance NAME]and an optional command-linebindoverride. The default is IPv4 loopback and the name-derived port. The bind setting acceptsADDRESS:PORT,[IPv6]:PORT,ADDRESS, and:PORT(which keeps the default loopback address). Hostnames are resolved once when settings are obtained; their original spelling is advertised unlessurl_hostoverrides it. The returned options includename,host,portandtokens, plus configuredpath,url_hostandurl_scheme. This does not start a listener. - @rules = $config->auto_rules ($name)
-
Return ordered automatic permission rules from
[program PROGRAM]and[instance NAME].auto-rule.SUFFIX = allow|deny TOOL[,ACTION[,CAPABILITY]]entries are sorted by key. The suffix is an arbitrary ordering label; instance entries override matching program entries, and an empty value disables an inherited entry. Command-line rules take precedence over these defaults. - $url = $config->http_url ($name, $bind, %options)
-
Format a URL containing the first accepted token, without listening. Port zero cannot be used because the kernel has not yet selected a port. When the token is derived, the master secret must be persistently stored, so the next process derives the same URL. Explicit static tokens and
auth => "none"do not require that persistence check.