ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/AnyEvent-MCP/lib/AnyEvent/MCP.pm
Revision: 1.3
Committed: Wed Oct 7 11:00:00 2026 UTC (5 weeks, 1 day ago) by root
Branch: MAIN
Changes since 1.2: +26 -3 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 =head1 NAME
2    
3     AnyEvent::MCP - Model Context Protocol client/server support
4    
5     =head1 SYNOPSIS
6    
7     use AnyEvent::MCP::Server::Simple;
8    
9     mcp_tool ...
10 root 1.3 mcp_start;
11 root 1.1
12     or use the object interface directly:
13    
14     use AnyEvent::MCP::Server;
15    
16     my $server = AnyEvent::MCP::Server->new (...);
17    
18     =head1 DESCRIPTION
19    
20     AnyEvent::MCP provides event-driven Model Context Protocol client and server
21     support.
22    
23     The usual way to implement a small MCP server is
24     L<AnyEvent::MCP::Server::Simple>, which provides a function-based interface and
25     creates the underlying server objects when a transport such as stdio or HTTP is
26     started.
27    
28     The lower-level object interfaces are intended for applications that need to
29     manage MCP connections, servers or reusable tool registries directly.
30    
31     =head2 MODULES
32    
33     =over 4
34    
35     =item L<AnyEvent::MCP::Server::Simple>
36    
37     Function-based interface for implementing ordinary MCP servers.
38    
39     =item L<AnyEvent::MCP::Server>
40    
41     Object-oriented MCP server interface.
42    
43     =item L<AnyEvent::MCP::Client>
44    
45     Object-oriented MCP client interface.
46    
47     =item L<AnyEvent::MCP::Server::Toolset>
48    
49     Reusable registry of MCP tool declarations.
50    
51     =item L<AnyEvent::MCP::Server::Permissions>
52    
53     Permission and capability handling for MCP servers.
54    
55     =back
56    
57     The interfaces are still being designed; this documentation is intentionally
58     only an overview for now.
59    
60 root 1.2 =head1 GLOBAL CONFIGURATION
61    
62     The shared per-user configuration is C<$XDG_CONFIG_HOME/anyevent-mcp/global.ini>,
63     or C<$HOME/.config/anyevent-mcp/global.ini> when XDG_CONFIG_HOME is unset.
64     L<AnyEvent::MCP::Config> loads and holds it; loading this module does not access
65     configuration files.
66    
67     The file is UTF-8 and uses sections with single-line C<key = value> pairs.
68     Values are unquoted strings. Blank lines and whole-line comments beginning
69     with C<#> or C<;> are ignored; inline comment characters remain part of the
70     value. Later occurrences of a key replace earlier ones in the same section.
71    
72     [global]
73     secret = ...128 hexadecimal digits...
74    
75     [server example]
76 root 1.3 port = 31740
77     url = https://example.net:31740/{cookie}/
78 root 1.2
79     [mcp-fs]
80     utility = /path/to/utility
81    
82     Section names are unrestricted. Application-specific sections, including
83     exports, utility paths and user settings, are documented by their applications.
84    
85     C<[global]> holds C<secret>, a 64-byte master key encoded as 128 hexadecimal
86     digits. The file must be owned by the current user, with no group or other
87     permissions. A missing secret is generated automatically on first configuration
88     access and saved when possible. Existing secrets are never replaced implicitly.
89     An invalid secret is an error.
90    
91     If saving fails, Config warns and retains the secret in memory. Credentials
92     then remain stable only for that process; other processes cannot derive the
93     same credentials. If randomness is unavailable, supply a securely generated
94     secret in the file.
95    
96     C<[server NAME]> holds named-server settings. Its C<url> is a complete template;
97     C<{cookie}> is replaced with the cookie derived for that server and optional
98     username. Scheme, host, port and cookie placement are explicit in the template.
99 root 1.3 HTTP servers with an explicit C<name> load C<host>, C<port>, C<path>,
100     C<url_host>, C<url_scheme>, C<cookie>, C<bearer> and C<users> from this section
101     as defaults. C<users> is a comma-separated allowlist whose Basic passwords
102     are derived for the named server. An explicit password hash can instead be
103     passed to the constructor. C<url> is a template for the utility program; it
104     does not set the listener's address.
105    
106     C<mcp_start> chooses an application name and supplies cookie/bearer
107     authentication by default. Explicit authentication settings replace this
108     default. Stdio startup does not access global configuration.
109    
110     C<[client NAME]> supplies HTTP client defaults: C<url>, C<bearer>, C<username>,
111     C<password> and C<timeout>. Clients consult it only when explicitly given a
112     C<name>. An unnamed client or HTTP server does not read global configuration.
113     Explicit constructor arguments take precedence over named defaults.
114    
115     =head1 ENVIRONMENT
116    
117     Project-specific environment variables use the C<PERL_ANYEVENT_MCP_> prefix.
118     C<PERL_ANYEVENT_MCP_MULTIBROKER_PROTOCOL=stdio> selects stdio in Simple.
119     C<PERL_ANYEVENT_MCP_MULTIBROKER_ALIAS> supplies the default application name.
120     C<PERL_ANYEVENT_MCP_PERMISSION_HELPER> selects the external asking executable.
121     Standard C<HOME> and C<XDG_CONFIG_HOME> keep their standard names.
122 root 1.2
123     =head1 FUNCTIONS
124    
125     =head2 $bytes = AnyEvent::MCP::random_bytes $length
126    
127     Returns exactly C<$length> random bytes. Tries C</dev/urandom>, then an external
128     C<openssl rand> command. No additional random-number module is required.
129     Dies if neither source supplies the requested bytes successfully.
130     C<$length> must be a nonnegative integer; zero returns an empty string.
131    
132 root 1.1 =cut
133    
134     package AnyEvent::MCP;
135    
136     use common::sense;
137     use Digest::SHA ();
138    
139     our $VERSION = '0.0';
140    
141 root 1.2 sub random_bytes($) {
142     my ($length) = @_;
143    
144     die "Invalid random byte count\n"
145     unless defined $length && $length =~ /\A[0-9]+\z/;
146     return "" unless $length;
147    
148     my $bytes = "";
149    
150     if (open my $fh, "<", "/dev/urandom") {
151     binmode $fh;
152     while (length $bytes < $length) {
153     read ($fh, $bytes, $length - length ($bytes), length $bytes)
154     or last;
155     }
156     close $fh;
157    
158     return $bytes if length $bytes == $length;
159     }
160    
161     if (open my $fh, "-|", "openssl", "rand", $length) {
162     binmode $fh;
163     local $/;
164     $bytes = <$fh>;
165     my $success = close $fh;
166    
167     return $bytes
168     if $success && defined $bytes && length $bytes == $length;
169     }
170    
171     die "Cannot obtain $length random bytes from /dev/urandom or openssl rand\n";
172     }
173    
174 root 1.1 sub hkdf_sha512_expand($$$) {
175     my ($prk, $info, $l) = @_;
176    
177 root 1.2 64 == length $prk
178     or die "hkdf_sha512_expand: prk length mist be 64 octets";
179    
180 root 1.1 my $t = "";
181     my $okm = "";
182     my $i = 0;
183    
184     do {
185     $t = Digest::SHA::hmac_sha512 $t . $info . chr ++$i, $prk;
186     $okm .= $t;
187     } while $l > length $okm;
188    
189     substr $okm, 0, $l
190     }
191    
192     sub _clean_text($) {
193     my ($text) = @_;
194    
195     my ($prefix) = (join "\n", grep /\S/, split /\n/, $text)
196     =~ /\A([ \t]*)[^\n]*(?:\n\1[^\n]*)*\z/;
197    
198     $text =~ s/^\Q$prefix\E//mg;
199     $text =~ s/\A\s+//;
200     $text =~ s/\s+\z//;
201     $text
202     }
203    
204     package AnyEvent::MCP::Base;
205    
206     sub new {
207     my ($class, %kv) = @_;
208     bless \%kv, $class
209     }
210    
211     sub event {
212     my ($self, $event, @args) = @_;
213     ($self->{"on_$event"} or return)->($self, @args)
214     }
215    
216     =head1 SEE ALSO
217    
218     L<AnyEvent>, L<https://modelcontextprotocol.io/>
219    
220     =head1 AUTHOR
221    
222     The main author of this module is OpenAI ChatGPT.
223    
224     Additional guidance received by:
225    
226     Marc Lehmann <schmorp@schmorp.de>
227     http://home.schmorp.de/
228    
229     =cut
230    
231     1
232