From bb6d0f305a374f23289ab1cfcaaf1fadb8760828 Mon Sep 17 00:00:00 2001 From: Artur Shiriev Date: Thu, 29 Oct 2026 22:55:19 +0300 Subject: [PATCH] feat: add a brand mark for modern-di-fastmcp --- brand/build/projects.py | 1 + brand/build/symbols.py | 26 ++++++++++++++++++ .../modern-di-fastmcp/lockup-dark.svg | 1 + .../modern-di-fastmcp/lockup-light.svg | 1 + brand/projects/modern-di-fastmcp/lockup.png | Bin 0 -> 2047 bytes .../projects/modern-di-fastmcp/mark-1024.png | Bin 0 -> 7649 bytes brand/projects/modern-di-fastmcp/mark-512.png | Bin 0 -> 3410 bytes brand/projects/modern-di-fastmcp/mark.svg | 1 + docs/index.md | 3 +- tests/test_projects.py | 1 + 10 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 brand/projects/modern-di-fastmcp/lockup-dark.svg create mode 100644 brand/projects/modern-di-fastmcp/lockup-light.svg create mode 100644 brand/projects/modern-di-fastmcp/lockup.png create mode 100644 brand/projects/modern-di-fastmcp/mark-1024.png create mode 100644 brand/projects/modern-di-fastmcp/mark-512.png create mode 100644 brand/projects/modern-di-fastmcp/mark.svg diff --git a/brand/build/projects.py b/brand/build/projects.py index 8890dcc..5567615 100644 --- a/brand/build/projects.py +++ b/brand/build/projects.py @@ -24,6 +24,7 @@ "modern-di-arq": lambda: sym.hopper(_CX, _CY, R), "modern-di-celery": lambda: sym.celery_stalk(_CX, _CY, R), "modern-di-fastapi": lambda: sym.bolt_disc(_CX, _CY, R), + "modern-di-fastmcp": lambda: sym.plug(_CX, _CY, R), "modern-di-faststream": lambda: sym.faststream(_CX, _CY, R), "modern-di-flask": lambda: sym.flask_horn(_CX, _CY, R), "modern-di-grpc": lambda: sym.rpc_arrow(_CX, _CY, R), diff --git a/brand/build/symbols.py b/brand/build/symbols.py index b2a6c06..9ec88b6 100644 --- a/brand/build/symbols.py +++ b/brand/build/symbols.py @@ -584,6 +584,32 @@ def rpc_arrow(cx: float, cy: float, r: float) -> str: return out +def plug(cx: float, cy: float, r: float) -> str: + """FastMCP cue: a plug, MCP being the port tools plug into, with a bolt knocked out.""" + bw, bh = 1.3 * r, 1.0 * r + top = cy - 0.6 * r + prong_w, prong_h = 0.21 * r, 0.45 * r + prongs = "".join( + f'' + for dx in (-0.3, 0.3) + ) + body = ( + f'' + ) + cord = ( + f'' + ) + bcy = top + bh / 2 + norm = [(0.12, -0.38), (-0.24, 0.07), (0.0, 0.07), (-0.12, 0.38), (0.24, -0.07), (0.0, -0.07)] + bolt = " ".join(f"{cx + dx * r:.1f},{bcy + dy * r:.1f}" for dx, dy in norm) + return prongs + body + cord + f'' + + def key(cx: float, cy: float, r: float) -> str: """jwks-client: a key, the signing key a JWKS publishes.""" sw = r * 0.2 diff --git a/brand/projects/modern-di-fastmcp/lockup-dark.svg b/brand/projects/modern-di-fastmcp/lockup-dark.svg new file mode 100644 index 0000000..3f6e791 --- /dev/null +++ b/brand/projects/modern-di-fastmcp/lockup-dark.svg @@ -0,0 +1 @@ + diff --git a/brand/projects/modern-di-fastmcp/lockup-light.svg b/brand/projects/modern-di-fastmcp/lockup-light.svg new file mode 100644 index 0000000..414276b --- /dev/null +++ b/brand/projects/modern-di-fastmcp/lockup-light.svg @@ -0,0 +1 @@ + diff --git a/brand/projects/modern-di-fastmcp/lockup.png b/brand/projects/modern-di-fastmcp/lockup.png new file mode 100644 index 0000000000000000000000000000000000000000..21f34b0f45bc4b448d8461d73199b54002846f0b GIT binary patch literal 2047 zcmV3}qt80000WbW%=J z1^)&Au>S&d{{#aB0sjE~{)d3hE)#D~uT3w~7ykziE+4Ts000LrNklw>B{ z41kpxb@c42wO0}4{onGmO|OW8f-^WL`E!O^(l#Gy(@=J2Ta-!33{CJmfXH1U674uD z5J?`FT_$M9QGqn9`-Gq!5eNc7AP5A3AP@wCfp$b^7s9tdPYKnxEAG94h62LhQ45a5A8 zrUJzAcuyb&ll+$f@jS){qI)}zvG~p5+5-cMPZ&sb_yhx=oWRBBs_Nn~J`nYCAPj85 zrVHe_zbR!0k9PploS$?HN>DM~DXZMykyamxJocx_12GPfYFz5;<(4m}3*@s2VV?Yb zczYnCF+J&WHSH*?$zzcMX*Kv^|3*`m{+IH63F-A(ND{&)0c8G_UA{e#Ezj4GzCg%J z*8RtU%s&>t49Inm^;ST>KIRByLO{OG`HY1?eiq2$e4dX2WX5^1ok`*5Zzg3nI<9|V znc=yqGRuH0nW>d%TyGgD1Y6tgaBVhe?yOB+ z(^l>Jl#j&r(Z$fvlCE((GxH#j`N#SEVPrlOhz>TT^ldVlCo7n8-3cWeI!R>&G85F7 z1&zdQvGp%DoK02u;0W$gJOI%uau4(yb?#aSJp+|HG27PugBtJ@_(6n`)Q#3$H%xuz z+Gk?`F+8j+_9FoC?Golkx6a0GN?4Z7FoX6$xN7uT-(|;2FBXVbqOK+yueu8ePd#;ImvA2JbsQc{;tZwc-yOJ$AD zo#CjSCAjco6P7Krj~=z214?DHSp`4Pb|A*fs1Sl1!|1B(+W0GhiaU0J2Dva#1`!g> zr`rPW^dpf0E^#Aq3S7VFtz_9lK;{c0IgcSgykVjH(ml;AjK@4+)MuA?ckMuuMV&jAHGH*K`&Oj$nH?d%b)?-P3kwS#8KUYa-{G_LIg>>%QOTk4-bel;J77-V$;NpI7$=`2rr zB|t)1Ba3S;WvS|kp7X)Rn8$g1hP|j)6!UYI{m5Qf<&>I&|18HOy zpU?L8^N@Q$l!zjSdx)}CNK$S>3B47qZ6xSss*80RRSfr#0YFZ-Qtw7S#|F|gnhL9S zx(r;;&-Z{N@1CL&WXBp};(=M{*(JTt`fw+Z+}B;->yFnheSjSAy)itF4J3P>Hw0sDs_$3+a#*(1j1pH>g?};h{OQmNg)4y-saJ6??FIBd@@-G zsl1ESezQp8cm!-x`T#My>$nl>2}A;YM!~+kCyHIss>K7dOAy83Y8P8>&>&A=^c&j5+-ZFGEpGopb^Lco)3l*n~*wg8FiNAxo5b;p#|`3kJMcRuc0-Wa~K^myWPAU$45x`^wzK_IUO(&rU%IL5dt5y*>y z^m}C=jeRwB}UXq^xy9ea)BY2zR9jhadrv-pKcO-IC9&WrgL?DBJi06-}R;$+6h6rR3 zkU>(OTHaD2ke>sho#aqrlri2m(PM2m}RzAP|%vPn{%!|5LDWfjpO7M0pty d6a?~b%U{fl&KCGJD*^xj002ovPDHLkV1o9ZoT>l- literal 0 HcmV?d00001 diff --git a/brand/projects/modern-di-fastmcp/mark-1024.png b/brand/projects/modern-di-fastmcp/mark-1024.png new file mode 100644 index 0000000000000000000000000000000000000000..b0245aee52865d9b56a17d49229c39d833b74346 GIT binary patch literal 7649 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 literal 0 HcmV?d00001 diff --git a/brand/projects/modern-di-fastmcp/mark-512.png b/brand/projects/modern-di-fastmcp/mark-512.png new file mode 100644 index 0000000000000000000000000000000000000000..8c185ca3e2768b861b7450b31290a1ce373584ef GIT binary patch literal 3410 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 literal 0 HcmV?d00001 diff --git a/brand/projects/modern-di-fastmcp/mark.svg b/brand/projects/modern-di-fastmcp/mark.svg new file mode 100644 index 0000000..43e7803 --- /dev/null +++ b/brand/projects/modern-di-fastmcp/mark.svg @@ -0,0 +1 @@ + diff --git a/docs/index.md b/docs/index.md index d417ba6..50d60c3 100644 --- a/docs/index.md +++ b/docs/index.md @@ -68,7 +68,8 @@ production Python services. Each project is independent, so use one piece or all [`modern-di`](https://github.com/modern-python/modern-di): typed, scoped dependency injection with one wiring shared across web frameworks (FastAPI, Litestar, Starlette, Flask, aiohttp), task queues (Celery, arq, taskiq), RPC - and messaging (gRPC, FastStream, aiogram), and CLIs (Typer). + and messaging (gRPC, FastStream, aiogram), MCP servers (FastMCP), and CLIs + (Typer). ([`that-depends`](https://github.com/modern-python/that-depends), the older DI framework, is still maintained.) - Call other services reliably with diff --git a/tests/test_projects.py b/tests/test_projects.py index 5c1b506..63326cb 100644 --- a/tests/test_projects.py +++ b/tests/test_projects.py @@ -47,6 +47,7 @@ def test_project_frame_parses_and_uses_tokens() -> None: "modern-di-taskiq", "modern-di-flask", "modern-di-grpc", + "modern-di-fastmcp", "jwks-client", "release-scope", }